5

In the context of Scientific Notation Only For Large Numbers have we been looking for a way to handle large numbers, as pgfmathparse can't cope with these. The only package we could find was bigintcalc, with the problem that it only works with integers.

MWE:

\documentclass{article}
\usepackage{bigintcalc}
\begin{document}
\bigintcalcSub{1}{100}
\end{document}

works fine, but

\documentclass{article}
\usepackage{bigintcalc}
\begin{document}
\bigintcalcSub{0.1}{100}
\end{document}

gives an error:

! Missing number, treated as zero.
<to be read again> 
                   .
l.4 \bigintcalcSub{0.1}{100}

So apparently \bigintcalcSub (or bigintcalc at all) is not the way to go. How can one handle large numbers that are not integers?

Edit: of course one can use an if statement to check if a number is big, and then only use it in that case, but that would be a bit hacky, wouldn't it?

Edit 2: to be more precise, we're trying to make a command that tests whether any number is greater than a certain threshold (and then do something if it is). There are both numbers as 0.01 and numbers as 1e75 fed to this command. pgfmathparse can do the first, bigintcalc can do the second, but is there something that can do both, so that the workarounds with if statements can be avoided and also large numbers that are not integers can be processed?

Betohaku
  • 1,637
  • 3
    The package is for dealing with integers (the clue is in the name): you want to deal with floating point or fixed point numbers. Could you explain the context better, and we can point to the best solution. – Joseph Wright May 08 '13 at 07:19
  • @JosephWright You're right, I have edited the question. – Betohaku May 08 '13 at 07:50

3 Answers3

6

The l3fp package can compute expressions involving floating points, with 16 significant digits, with a large range of exponents (currently positive numbers range in [10^-10000, 10^10000], but this may change a bit). If 16 digits is enough for your purposes, you could use that. Some day, I'll code an arbitrary precision floating point unit, but that takes time.

\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}
  • Sadly, we need to display numbers such as 1e75, as described in the question. But thanks for the suggestion. – Betohaku May 08 '13 at 09:28
  • @Betohaku I don't see the issue: l3fp can manipulate numbers from 1e-10000 to 1e10000 (and negative numbers too). The question is whether your numbers have more than 16 significant figures, e.g., 1.23456789123456789e75 would be rounded to 1.234567891234568e75, which may be a problem in some applications. – Bruno Le Floch May 08 '13 at 09:50
  • In that case I misread the ambiguous range [-10000,10000] as being a range between these numbers instead of exponents of these numbers. I apologize. – Betohaku May 08 '13 at 09:54
  • I have now taken a good look at http://archive.cs.uu.nl/mirror/CTAN/macros/latex/contrib/l3kernel/expl3.pdf, but I couldn't find how to apply it to http://tex.stackexchange.com/questions/111670/scientific-notation-only-for-large-numbers/ (where the problem arose). Apparently LaTeX doesn't like $ in if statements and pgfmathparse. Do you have any suggestions? – Betohaku May 08 '13 at 10:30
  • 2
    @Betohaku I don't know what you tried: in particular, I don't understand where you tried putting $. Does it have a special meaning in pgfmath? Replacing \IfLessThanOrEqual{#2}{\ThresholdLow}{...}{...} by \fpcmpTF{abs(#2)<=\ThresholdLow}{...}{...} in your self-answer (with \fpcmpTF defined as \fp_compare:nTF) should work (of course, \IfGreaterThanOrEqual should be changed in the same way). – Bruno Le Floch May 08 '13 at 12:19
  • This is perfect! I will add your suggestion to the answer. FYI: it wasn't a self-answer (questioner != me) :P. – Betohaku May 08 '13 at 12:53
4

run with lualatex

\documentclass{article}
\begin{document}
$0.1-100$ is $\directlua{tex.print(0.1-100)}$
\end{document}
2

The package xintfrac may be used for such computations. The package is primarily concerned with computations, not typesetting, so I have added here a little macro to transmit the typesetting task to other packages such as siunitx or numprint.

Update: I wondered in the comments to the code below if wrapping across lines was possible with siunitx, or with numprint in mathmode. From very brief examination of some log a test document using \showoutput it seems that

  1. siunitx puts the whole thing in a \hbox, whether in math mode or in text, and additionally also encloses the thousand separator in a \hbox,
  2. numprint, when in math mode, typesets the thousand separator in a \hbox, but when in text mode, it does not: hence with numprint+text mode wrapping is possible (the entire thing is fortunately not enclosed in a \hbox), but in math mode it does not seem to be.

I apologize for these details perhaps only indirectly related to the OP's question: but if we are to subtract power of tens like 10^{100}-1, we have to think about how to print the resulting one hundred nine's.

\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}

enter image description here