在仅适用于大数的科学记数法我们一直在寻找一种处理大数的方法,因为我们pgfmathparse
无法处理这些。我们能找到的唯一包是bigintcalc
,但问题是它只适用于整数。
梅威瑟:
\documentclass{article}
\usepackage{bigintcalc}
\begin{document}
\bigintcalcSub{1}{100}
\end{document}
工作正常,但是
\documentclass{article}
\usepackage{bigintcalc}
\begin{document}
\bigintcalcSub{0.1}{100}
\end{document}
给出错误:
! Missing number, treated as zero.
<to be read again>
.
l.4 \bigintcalcSub{0.1}{100}
因此显然\bigintcalcSub
(或者bigintcalc
根本不是)可行之道。如何处理非整数的大数?
编辑:当然,我们可以使用 if 语句来检查一个数字是否很大,然后只在这种情况下使用它,但这有点不礼貌,不是吗?
编辑2:更准确地说,我们试图制作一个命令来测试任何数字是否大于某个阈值(如果是,则执行某些操作)。这个命令中既有 0.01 的数字,也有 1e75 的数字。pgfmathparse
可以执行第一个,bigintcalc
可以执行第二个,但是有没有可以同时执行这两个操作的东西,这样就可以避免使用 if 语句的解决方法,也可以执行较大的数字不是整数可以处理吗?
答案1
该l3fp
包可以计算涉及浮点的表达式,具有 16 位有效数字,指数范围很大(目前正数范围为 [10^-10000, 10^10000],但这可能会有所变化)。如果 16 位数字足以满足您的目的,您可以使用它。有一天,我会编写一个任意精度的浮点单元,但这需要时间。
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new_eq:NN \fpeval \fp_eval:n
\cs_new_eq:NN \fpcmpTF \fp_compare:nTF
\ExplSyntaxOff
\begin{document}
$0.1-100$ is $\fpeval{0.1-100}$, and it is
\fpcmpTF{0.1-100 < -99}{greater}{smaller} than $-99$.
\end{document}
答案2
运行lualatex
\documentclass{article}
\begin{document}
$0.1-100$ is $\directlua{tex.print(0.1-100)}$
\end{document}
答案3
包xintfrac
可用于此类计算。包主要关注计算,而不是排版,因此我在这里添加了一个小宏,将排版任务传输给其他包,例如siunitx
或numprint
。
更新:我在以下代码的评论中想知道,使用 siunitx 或数学模式下的 numprint 是否可以换行。从对一些使用 log 的测试文档的非常简短的检查来看,\showoutput
似乎
siunitx
将整个内容放在 中\hbox
,无论是在数学模式还是在文本中,另外还将千位分隔符放在\hbox
中numprint
在数学模式下,将千位分隔符排版为\hbox
,但在文本模式下则不会这样:因此可以使用numprint
+text mode
换行(幸运的是,整个内容都not
包含在 中\hbox
),但在数学模式下似乎不行。
我很抱歉,这些细节可能仅与 OP 的问题间接相关:但是如果我们要减去十的幂10^{100}-1
,我们就必须考虑如何打印结果的一百九。
\documentclass{article}
\usepackage{color} % for testing an option of siunitx
% formatting numbers with macro \np of numprint
% http://www.ctan.org/tex-archive/macros/latex/contrib/numprint
\usepackage[np]{numprint}
\npthousandsep{\allowbreak\,}
% The \allowbreak allows very long numbers to wrap at endlines
% (but does not work in math mode, I didn't investigate why, perhaps numprint
% uses an \hbox)
\npdecimalsign{.}
% formatting with macro \num of siunitx
% http://www.ctan.org/tex-archive/macros/latex/exptl/siunitx
% I don't know if very long numbers
% wrapping at endlines are possible with it. I tried the following option but it
% doesn't do what I hoped for:
\usepackage[group-separator={\allowbreak\,}]{siunitx}
% computes expandably with long fractions and decimal numbers
% http://www.ctan.org/tex-archive/macros/generic/xint
\usepackage{xintfrac}
% The next macro prepares a decimal fraction as output by macros of the xintfrac
% package for printing by specialized software.
% Another macro could be written to directly prepare the number in scientific
% notation, but here we simply prepare the number in a.b form with b the
% possibly empty strings of digits after the decimal mark (which is a dot), and
% the transformation into scientific notation can be done at the level of the
% typesetting package.
% The first parameter to \decprint is optional and is the command to be applied.
% The default is \np from the numprint package. But one may use for example
% [{\num[key=value]}] to employ \num from the siunitx package with some options.
% The second argument is mandatory and is the decimal number to be typeset. On
% input, xintfrac understands the following format: a, or a.b, or a[c], or
% a.b[c], where [c] means 10 to the power c, and a and b are strings of digits.
% Example: \decprint {\xintAdd {1[-10]}{1[10]}}, which first computes the sum of
% 1e-10 and 1e10 (xintfrac does not understand the scientific notation, it uses
% brackets rather than e or E) and then
% prints the result using \np command from numprint package.
\makeatletter
\newcommand{\decprint}[2][\np]
{\expandafter\expandafter\expandafter\dec@print\xintREZ{#2}{#1}}
\def\dec@print #1/#2[#3]#4{%
\ifnum #3<0
\expandafter\@firstoftwo
\else\expandafter\@secondoftwo
\fi
{#4{\xintTrunc {-#3}{#1[#3]}}}% non-zero digits after decimal point
{#4{\xintDSH {-#3}{#1}}}% number is an integer, no decimal point needed
\ifcase\XINT@isOne{#2}
\expandafter\@firstofone % unexpected, denominator wasn't power of ten
\or\expandafter\@gobble
\fi {/#4{#2}}}
\makeatother
\begin{document}
$0.1-100$ is $\decprint{\xintSub{0.1}{100}}$, and it is
\ifcase\xintCmp{\xintSub{0.1}{100}}{-99}
equal \or greater \else smaller \fi than $-99$.
$0.01-10^{10}$ is \decprint{\xintSub{0.01}{1[10]}}.
$0.01-10^{10}$ is \decprint[\num]{\xintSub{0.01}{1[10]}}.
$0.01-10^{75}$ is \decprint{\xintSub{0.01}{1[75]}}.
$0.01-10^{75}$ is \decprint[{\num[mode=text]}]{\xintSub{0.01}{1[75]}}.
$3.14-\np{5e-15}+\np{3e15}$ is \decprint{\xintSumExpr
{3.14}{-5[-15]}{3[15]}\relax }
$3.14-\np{5e-15}+\np{3e15}$ is \decprint[{\num[mode=text]}]{\xintSumExpr
{3.14}{-5[-15]}{3[15]}\relax }
$3.14-\np{5e-25}+\np{3e25}$ is \decprint{\xintSumExpr
{3.14}{-5[-25]}{3[25]}\relax } and we could make it wrap accross lines using
\textbackslash np.
$3.14-\np{5e-25}+\np{3e25}$ is \decprint[{\num[color=blue]}]{\xintSumExpr
{3.14}{-5[-25]}{3[25]}\relax } and we tried but failed to let it wrap
accross lines using \textbackslash num.
\end{document}