8

The following is a MWE, which explains my intention.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{math}
\begin{document}
\tikzmath{
\integer = 4/2; \decimal = 5/3; 
\integerB=1/3*3;
}
$\integer$ is an integer, and it should be printed as 2. 
And $\decimal$ is a decimal number, I would like to round it to 1.7. 
Another difficulty is that $\integerB$  is an integer in fact, 
and should be printed as 1. 
\end{document}

I wonder if it is possible to test a number to determine it is an integer. Alternatively, it would also be great if it is possible to determine whether the first two decimal numbers are sufficiently close to 0 or 1.

5 Answers 5

3

enter image description here

\documentclass{article}
\usepackage{xintexpr}% recommended package

\newcommand\test[1]{\xintifboolexpr{ifint(#1, 1, 0)}
  {\xinttheexpr reduce(#1)\relax\space (originally \texttt{\detokenize{#1}})
   is an integer.}
  {\xinttheiexpr[2] #1\relax\space (originally \texttt{\detokenize{#1}}), 
   we rounded to two decimal places) is not an integer.}\par
}

\begin{document}

\test{4/2}

\test{5/3}

\test{(1/3)*3}

\test{(1/7 - 1/8 - 1/57)*3192}

\test{(1/2 - 1/3 - 1/7 - 1/43 - 1/1807 - 1/3263443)*10650056950806}

\end{document}

enter image description here

4
  • strangely xintexpr has ifint(expression, YES, NO) function but not isint(expression) which would evaluate to 1 or 0 directly.
    – user4686
    Jan 1, 2019 at 13:21
  • about "Alternatively, it would also be great if it is possible to determine whether the first two decimal numbers are sufficiently close to 0 or 1." this can be done by xintexpr of course as it computes exactly with arbitrarily big fractions. But I don't know exactly what is asked here.
    – user4686
    Jan 1, 2019 at 13:23
  • for comparison \fpeval{(1/2 - 1/3 - 1/7 - 1/43 - 1/1807 - 1/3263443)*10650056950806} evaluates to 0.9999211586333241, exactly like \xintthefloatexpr...\relax. But the latter after \xintDigits:=48; will evaluate to 1.00000000000000000000000000000000000522205263811.
    – user4686
    Jan 1, 2019 at 13:46
  • FWIW, using the default precision settings, Lua evaluates (1/2 - 1/3 - 1/7 - 1/43 - 1/1807 - 1/3263443)*10650056950806 as 1.000285363444. Of course, \round{\comp{(1/2 - 1/3 - 1/7 - 1/43 - 1/1807 - 1/3263443)*10650056950806}}{1} (where \round and \comp are defined in my answer) produces 1. Whew!
    – Mico
    Jan 1, 2019 at 14:08
6

One cannot say from its floating point representation whether the output of an arithmetic operation involving division or non rational operations is actually an integer.

You can consider the l3fp module of expl3, available through the package xfp.

\documentclass{article}
\usepackage{xfp}

\begin{document}

$\fpeval{5/3}$ is a decimal number, I would like to round it to
$\fpeval{round(5/3,1)}$ or to $\fpeval{round(5/3,2)}$

Another difficulty is that $\fpeval{(1/3)*3}$ is an integer in fact, 
and should be printed as $\fpeval{round((1/3)*3,1)}$ or
$\fpeval{round((1/3)*3,2)}$.

\end{document}

enter image description here

4

If the accuracy of your numbers is important you might consider farming that out to a computer algebra system (CAS). The sagetex package relies on the CAS Sage; the documentation can be found on CTAN right here. Documentation on Sage is found here .Sage is not part of the LaTeX distribution (it's big) so it needs to be installed on your computer or, even easier, accessed through a free Cocalc account.

\documentclass{article}
\usepackage{sagetex}
\usepackage{tikz}
\usetikzlibrary{math}
\begin{document}
\begin{sagesilent}
a = 4/2
b = 5/3
c = 1/3*3
\end{sagesilent}
$\sage{a}$ is an integer, and it should be printed as     $\sage{a}$. 
And $\sage{b}$ is not an integer. As a decimal it is     approximately
$\sage{b.n(digits=6)}$. I would like to round it to     $\sage{b.n(digits=1)}$. 
Another difficulty is that $\sage{c}$ is an integer in fact, 
and should be printed as $\sage{c}$. 
\end{document}

The output, running in Cocalc, gives: enter image description here

Notice that Sage interprets your numbers correctly: 4/2 is recognized as 2 and 1/3*3 is recognized as 1. It does need to know the format you want of non integers; but it recognizes that 5/3 is a fraction that can't be reduced and leaves it as a fraction. To force it into a decimal and to specify the number of digits we append .n(digits=6); the documentation is here.

4

Assuming that this is a question on how to do this with tikzmath, I'd do

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{math}
\begin{document}
\tikzmath{
function myint(\x) {
    if abs(\x-round(\x)) < 0.1 then { print{\x\ is an integer\newline};
      return int(round(\x));
    } else { print{\x\ is not an integer\newline};
       return \x;
}; };
\integer = myint(4/2); 
\decimal = myint(5/3);
\integerB= myint(1/3*3);
}


$\integer$ is an integer, and it should be printed as 2. 
And $\pgfmathprintnumber[precision=1]{\decimal}$ is a decimal number, I would like to round it to 1.7. 
Another difficulty is that $\integerB$  is an integer in fact, 
and should be printed as 1. 
\end{document}

enter image description here

Note that I used \pgfmathprintnumber to round to one digit after the dot. Of course, you can remove the prints.

1

Here's a LuaLaTeX-based solution. \integer (4/2) and \integerB ((1/3)*3) evaluate to integers automatically according to Lua rules. The LaTeX macro \round, which takes two arguments, lets users round numbers to a specified set of digits after the decimal marker.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
% Set up 2 auxilliary Lua functions to round numbers
\directlua{
function math.round_int ( x )
   return x>=0 and math.floor(x+0.5) or math.ceil(x-0.5)
end
function math.round ( x , n )
  return ( math.round_int ( x*10^n ) / 10^n )
end
}
\newcommand\comp[1]{\directlua{tex.sprint(#1)}}
\newcommand\round[2]{\directlua{tex.sprint(math.round(#1,#2))}}

\newcommand{\integer}{\comp{4/2}}
\newcommand{\decimal}{\comp{5/3}} 
\newcommand{\integerB}{\comp{(1/3)*3}}

\begin{document}
\integer\ is an integer. 

\integerB\ is also an integer. 

\decimal\ is a decimal number. I would like to round it to \round{\decimal}{1}.
\end{document}
4
  • 1
    does (1/7-1/8-1/57)*3192 evaluate to an integer in Lua? (just curious...)
    – user4686
    Jan 1, 2019 at 13:37
  • 1
    in case answer is yes (perhaps from some distributivity done automatically), I have (1/7 - 1/8 - 1/57)*(3000+192) up my sleeve :)
    – user4686
    Jan 1, 2019 at 13:43
  • @jfbu - Both expressions evaluate to 0.99999999999998 (13 nines followed by an 8), using the standard number of significant digits used in tex.sprint. If I reduced that number by 1 or 2 digits, one is back to 1 (pun intended).
    – Mico
    Jan 1, 2019 at 13:46
  • 2
    I think \xintthefloatexpr works with \xintDigits:=2; but I am not sure with only 1 digit :) you are really quite a challenge!
    – user4686
    Jan 1, 2019 at 13:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .