如何减去非常大的数字和小于一的数字?

如何减去非常大的数字和小于一的数字?

仅适用于大数的科学记数法我们一直在寻找一种处理大数的方法,因为我们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可用于此类计算。包主要关注计算,而不是排版,因此我在这里添加了一个小宏,将排版任务传输给其他包,例如siunitxnumprint

更新:我在以下代码的评论中想知道,使用 siunitx 或数学模式下的 numprint 是否可以换行。从对一些使用 log 的测试文档的非常简短的检查来看,\showoutput似乎

  1. siunitx将整个内容放在 中\hbox,无论是在数学模式还是在文本中,另外还将千位分隔符放在\hbox
  2. 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}

在此处输入图片描述

相关内容