我正在使用 MathJax-Node 将 TeX 数学方程式转换为 MathML 和 SVG。大部分情况下,这都很好用。但当我渲染塔珀的自我参照公式,指数中的第二个减号后面出现了一个奇怪的空格:。
该空间还出现在数学网址(上图就是由此而来的)。当我检查生成的 MathML 时,我可以看到 MathJax 明确插入了一个mspace
元素。
我使用的 TeX 如下:
\frac12<\left\lfloor\mod\left(\left\lfloor\frac y{17}\right\rfloor2^{{-17}\left\lfloor x\right\rfloor-\mod\left(\left\lfloor y\right\rfloor,17\right)},2\right)\right\rfloor
知道这里发生什么事了吗?
答案1
您使用“mod”作为数学运算符,如“exp”或“sin”。该命令\mod
用于表示法,例如
5 \equiv 2 \mod{3}
并且这里显然需要插入空格。
改用\operatorname{mod}
。
\documentclass{article}
\usepackage{amsmath}
\begin{document}
\[
\frac{1}{2}<
\left\lfloor
\operatorname{mod}\left(
\left\lfloor\frac{y}{17}\right\rfloor
2^{-17\lfloor x\rfloor-\operatorname{mod}(\lfloor y\rfloor,17)},2
\right)
\right\rfloor
\]
\end{document}
我已经删除了无用的(和错误的)\left
和\right
对。
它在 MathJax 中同样有效(在 Math.SE 上测试):
答案2
你的意思是:
\documentclass{article}
\usepackage{xintexpr}
% Tupper
% q = floor(y/17)
% r = mod(y, 17) (modulo for floor)
% Tupper formula boils down to say:
% Pixel (x, y) is ON <===> floor(q, 2**(17x+r)) is ODD
% https://fr.wikipedia.org/wiki/Formule_autor%C3%A9f%C3%A9rente_de_Tupper
% \xintiiexpr notations
% floored division is //
% associated modulo is /: (or 'mod')
% divmod(,) is both // and /: (as in Python)
\begin{document}
% 0 <= x < 106
% k <= y < k + 17
\xintdefiivar TupperK :=
960939379918958884971672962127852754715004339660129306651505519271702802395266
424689642842174350718121267153782770623355993237280874144307891325963941337723
487857735749823926629715517173716995165232890538221612403238855866184013235585
136048828693337902491454229288667081096184496091705183454067827731551705405381
627380967602565625016981482083418783163849115590225610003652351370343874461848
378737238198224849863465033159410054974700593138339226497249461751545728366702
369745461014655997933798537483143786841806593422227898388722980000748404719;
\setlength\unitlength{1pt}
\def\parseTupperXY#1#2{% #1 = x, #2=y,
\xintdefiivar Yq, Yr = divmod(#2, 17);%
\edef\resultTupperXY{\xinttheiiexpr odd(Yq // 2**(17 * #1 + Yr))\relax}%
}%
% This is a bit slow, be patient (big powers of 2 are computed...)
% Much faster would be to convert TupperK to binary...
\begin{picture}(106,17)
\xintFor* #1 in {\xintSeq{0}{105}}\do {% x
\xintFor* #2 in {\xintSeq{0}{16}}\do {% y - k
\parseTupperXY{#1}{#2+TupperK}
\if1\resultTupperXY
\put(\numexpr105-#1, \numexpr16-#2){\rule{1pt}{1pt}}
\fi
}
}
\end{picture}
\end{document}
我希望这
\documentclass{article}
\usepackage{xintexpr}
% Tupper
% q = floor(y/17)
% r = mod(y, 17) (modulo for floor)
% Tupper formula boils down to say:
% Pixel (x, y) is ON <===> floor(q, 2**(17x+r)) is ODD
% https://fr.wikipedia.org/wiki/Formule_autor%C3%A9f%C3%A9rente_de_Tupper
% \xintiiexpr notations
% floored division is //
% associated modulo is /: (or 'mod')
% divmod(,) is both // and /: (as in Python)
\begin{document}
% 0 <= x < 106
% k <= y < k + 17
\xintdefiivar TupperK :=
960939379918958884971672962127852754715004339660129306651505519271702802395266
424689642842174350718121267153782770623355993237280874144307891325963941337723
487857735749823926629715517173716995165232890538221612403238855866184013235585
136048828693337902491454229288667081096184496091705183454067827731551705405381
627380967602565625016981482083418783163849115590225610003652351370343874461848
378737238198224849863465033159410054974700593138339226497249461751545728366702
369745461014655997933798537483143786841806593422227898388722980000748404719;
\setlength\unitlength{1pt}
\xintdefiivar twoToThe17 := 2**17;
\xintdefiivar twoToThe17timesX := 1;
\begin{picture}(106,17)
\xintFor* #1 in {\xintSeq{0}{105}}\do {% x
\xintFor* #2 in {0123456789{10}{11}{12}{13}{14}{15}{16}}\do {% y - k
\xintdefiivar Yq, Yr = divmod(#2 + TupperK, 17);%
\xintifbooliiexpr {odd(Yq // (twoToThe17timesX * 2**Yr ))}
{\put(\numexpr105-#1, \numexpr16-#2){\rule{1pt}{1pt}}}
{}
}
\xintdefiivar twoToThe17timesX := twoToThe17 * twoToThe17timesX;%
}
\end{picture}
\end{document}
会更快,但只是快了一点点。因此瓶颈在于大的除法,而不是 2 的幂。
例如,稍微作弊并计算k
via的二进制表示形式会更快。\xintDecToBin
xintbinhex
使用实数公式计算像素
上面的内容有点作弊:实际使用的确定像素是否为 ON 的公式与原始公式略有不同,因为它仅使用整数算法。当然,可以使用\xintexpr
而不是\xintiiexpr
并执行“实际”操作……当然,这会慢一点。(仍然)
\documentclass{article}
\usepackage{xintexpr}
% Tupper
% q = floor(y/17)
% r = mod(y, 17) (modulo for floor)
% Tupper formula is (exactly) (apart from using floor rather than ⌊ and ⌋)
% Pixel (x, y) is ON <===> 1/2 < floor(mod(floor(y/17)2**(-17x-mod(y, 17)), 2))
% The latter means floor(q, 2**(17x+r)) is ODD, when using only
% integers
% but here we will be using the REAL THING !
\begin{document}
% 0 <= x < 106
% k <= y < k + 17
\xintdefiivar TupperK :=
960939379918958884971672962127852754715004339660129306651505519271702802395266
424689642842174350718121267153782770623355993237280874144307891325963941337723
487857735749823926629715517173716995165232890538221612403238855866184013235585
136048828693337902491454229288667081096184496091705183454067827731551705405381
627380967602565625016981482083418783163849115590225610003652351370343874461848
378737238198224849863465033159410054974700593138339226497249461751545728366702
369745461014655997933798537483143786841806593422227898388722980000748404719;
\setlength\unitlength{1pt}
% SLOW ! (about 55s on 2.4Ghz laptop)
\begin{picture}(106,17)
\xintFor* #1 in {\xintSeq{0}{105}}\do {% x
\xintdefiivar x = #1;% to let the formula use X, Y, not #1, #2
\xintFor* #2 in {0123456789{10}{11}{12}{13}{14}{15}{16}}\do {% y - k
\xintdefiivar y = #2 + TupperK;%
\xintifboolexpr
% TUPPER FORMULA USED AS INPUT SHOWS IN OUTPUT
% EXCEPT WE USE floor NOT ⌊, ⌋ AS THIS IS XINTEXPR SYNTAX
{1/2 < floor(mod(floor(y/17)2**(-17x-mod(y, 17)), 2))}
{\put(\numexpr105-#1, \numexpr16-#2){\rule{1pt}{1pt}}}
{}
}
}
\end{picture}
\end{document}
通过二进制数字作弊,更快地构建图片
在另一个方向上,我们可以完全作弊,对k/17
原始公式进行分析,将其转换为二进制数字,即当某位为 1 时,像素为开。自然,图像的生成速度会更快。
\documentclass{article}
\usepackage{xintexpr}
% Tupper
% q = floor(y/17)
% r = mod(y, 17)
% Tupper formula boils down to say:
% Pixel (x, y) is ON <===> floor(q / 2**(17x+r)) is ODD
% https://fr.wikipedia.org/wiki/Formule_autor%C3%A9f%C3%A9rente_de_Tupper
% This also means that
% Pixel (x, y) is ON <==> 17x+r bit of q is 1
% where "Oth bit" means least significant bit aka parity bit.
% Specific case
% 0 <= x < 106
% k <= y < k + 17
% Where k is a multiple of 17, k = 17 q
% Then we get binary bits of q starting from least significant one
% by chunks of 17 for each x = 0, 1, ...
% The value given for k at wikipedia page is
\xintdefiivar TupperK :=
960939379918958884971672962127852754715004339660129306651505519271702802395266
424689642842174350718121267153782770623355993237280874144307891325963941337723
487857735749823926629715517173716995165232890538221612403238855866184013235585
136048828693337902491454229288667081096184496091705183454067827731551705405381
627380967602565625016981482083418783163849115590225610003652351370343874461848
378737238198224849863465033159410054974700593138339226497249461751545728366702
369745461014655997933798537483143786841806593422227898388722980000748404719;
\xintdefiivar TupperQ, TupperR := divmod(TupperK, 17);
\xintifboolexpr{TupperR}
{% remainder would be not zero, which is not the case with this k
\ERROR
}
{% remainder is zero as expected
\typeout{k is multiple of 17: k mod 17 = \xinttheiiexpr TupperR\relax}
}
% Now we will assign the binary digits of q to an "array" for later use
\usepackage{xintbinhex}
\xintAssignArray
\xintReverseDigits
{\xintDecToBin{\xinttheiiexpr TupperQ\relax}}\to
\TupperBits
% We need 1802 = 106 * 17 bits, but turns out the two leading ones are zero
% so \TupperBits{index} only works 1<= index <= 1800
% xinttools should definitely be extended to have array-extension macro
% but it only has the very starts of "array" concept so we will need to
% add a check in the loop using it.
\typeout{Binary rep of k/17 has only \TupperBits{0} bits, not \the\numexpr106*17.}
\begin{document}
\setlength\unitlength{1pt}
% Now we use the binary digits of q = k/17
% \TupperBits items are enumerated starting at 1 not at 0
\begin{picture}(106,17)
\xintFor* #1 in {\xintSeq{0}{105}}\do {%
% #1 will be x
\xintFor* #2 in {0123456789{10}{11}{12}{13}{14}{15}{16}}\do {%
% #2 will be y mod 17
% Due to possibly vanishing leading bits
\ifnum \numexpr#1*17+#2+1>\TupperBits{0}
\else
\if1\TupperBits{#1*17+#2+1}% charms of expandability
% The x coordinate goes from right to left and the y from top to bottom
% in Tupper plane
\put(\numexpr105-#1, \numexpr16-#2){\rule{1pt}{1pt}}
\fi
\fi
}
}
\end{picture}
\end{document}
使用“楼层”而不是左楼层和右楼层符号的变体
原始配方
1/2<floor(mod(floor(y/7)2^(-7x-mod(y,7)),2))
平面区域
0 <= x < 308, k <= y < k + 7
如下k
所示。
我从公式开始,用一些在线转换器将其转换为 ascii-art。结果它产生了 8 行,其中一行是空的。所以我用 7 代替公式中的 17,然后重新开始。最后,我将位数组转换为某个数字,乘以 7 后就是这个:
k = 38426720969186584676507136423746315165273305413945565187145665641304238215561995317662843293085432836310036135900849286588951953665639729939317005809629409803737705286494507269624061838603195349517975717012314034034886568013639993815956512735232451156976667291853312484643760872115994758595671605381979339411956400072599436927196143537882844410760247627090690368478688405508823263940609428350186251562536135575229759753524677106213338248890237354234165603070460931515868266696814935467260883698401252476941050712407716221704528350212280853722118440152424270081709425589819079391652824219385549071663086397901966417260775437015400315493361455291308484
它有 650 个十进制数字,并且k/7
有2156 = 308*7
二进制数字。
原始公式位于区域0<= x < 308
,k <= y < k+7
如上所示k
。我使用的是像素化平面,其中 x 从右到左增加,y 从上到下增加, 处的单位像素的(x,y)
左下角位于(x,y)
。
因此,该公式在评估中确实使用实数,但是x, y
是整数。
遗憾的是,由于 xintexpr 使用控制序列字符串来存储标记,TeX 内存耗尽。因此,由于我花了一些时间进行设置,我恢复为直接从(计算的)二进制数字排版图片。
\documentclass{article}
\usepackage{xintexpr}
% Tupper+xintexpr
% FORMULA:
% Pixel (x, y) is ON <===> 1/2 < floor(mod(floor(y/7)2**(-7x-mod(y,7)),2))
% 0 <= x < 308
% k <= y < k + 7
\xintdefiivar TupperKvariant :=
38426720969186584676507136423746315165273305413945565187145665641304238215561995317662843293085432836310036135900849286588951953665639729939317005809629409803737705286494507269624061838603195349517975717012314034034886568013639993815956512735232451156976667291853312484643760872115994758595671605381979339411956400072599436927196143537882844410760247627090690368478688405508823263940609428350186251562536135575229759753524677106213338248890237354234165603070460931515868266696814935467260883698401252476941050712407716221704528350212280853722118440152424270081709425589819079391652824219385549071663086397901966417260775437015400315493361455291308484;
% Turns out that here k/7 has 2156 bits (= 308*7)
% conversion to binary for "cheating approach"
\usepackage{xintbinhex}
\xintdefiivar TupperQvariant := TupperKvariant/7;
\xintAssignArray
\xintReverseDigits
{\xintDecToBin{\xinttheiiexpr TupperQvariant\relax}}\to
\TupperBits
% no missing "0" leading bit in that case, length is 2156=308*7
\begin{document}
\setlength\unitlength{1pt}
% \begin{picture}(308,7)
% \xintFor* #1 in {\xintSeq{0}{307}}\do {% x
% \xintdefiivar x = #1;% to let the formula use x, y, not #1, #2
% \xintFor* #2 in {0123456}\do {% y - k
% \xintdefiivar y = #2 + TupperKvariant;%
% \xintifboolexpr
% % MODIFIED TUPPER FORMULA USED IN INPUT SHOWS AS IS IN OUTPUT!
% {1/2<floor(mod(floor(y/7)2^(-7x-mod(y,7)),2))}
% {\put(\numexpr307-#1, \numexpr6-#2){\rule{1pt}{1pt}}}
% {}
% }
% }
% \end{picture}
% ARRGGGGGGGGGGGHHHHHH after about 90s
% ! TeX capacity exceeded, sorry [pool size=6162206].
% <argument> ...535738417728939435264785252352[0],2
% so we do it by cheating
\begin{picture}(308,7)
\xintFor* #1 in {\xintSeq{0}{307}}\do {%
% #1 will be x
\xintFor* #2 in {0123456}\do {%
% #2 will be y mod 7
% no vanishing leading bits
\if1\TupperBits{#1*7+#2+1}% charms of expandability
% The x coordinate goes from right to left and the y from top to bottom
% in Tupper plane
\put(\numexpr307-#1, \numexpr6-#2){\rule{1pt}{1pt}}
\fi
}
}
\end{picture}
\end{document}