I have known that I can use "advance...by..." to do arithmetic on number in TeX, but is there any way to do arithmetic without changing the value of number? For example, if I want to determine whether a number called X whose value is x satisfies x^2+x+1<0, and keep the former value of X for future use, what can I do?
2 Answers
You can e.g. use xfp:
\documentclass{article}
\usepackage{xfp}
\newcommand\myxvalue{15}
\begin{document}
\ifnum \fpeval{\myxvalue^2 + \myxvalue + 1} < 0 \relax
yes
\else no: it is \fpeval{\myxvalue^2 + \myxvalue + 1}
\fi
\end{document}
- 327,261
-
this does not sound robust because a priori
\fpevalproduces floating point numbers (as digit tokens with dot) which would immediately cause problems with\ifnum. (for example if computations needs more then 16 digits of precision) Hasn't LaTeX3 introduced\numevalor\inteval? but maybe this is only a wrapper to\numexprhence no^operator. – Mar 20 '18 at 13:12 -
@jfbu yes you are right. One would have to use also the tests from l3fp. – Ulrike Fischer Mar 20 '18 at 13:37
-
Thinking again, I would expect your answer to be perfectly fine with integer only computations as long as final result fits in TeX bound (it appers, but I have not checked really, that
\fpevalwill not output15.0for example but15), but the problem is with/which is not rounded integer division hence a discrepancy with\numexprbased computations. – Mar 20 '18 at 14:42 -
-
\xinttheiexpr \xintfloatexpr\myxvalue^1000/\myxvalue^999\relax\relaxis only about 2.5x slower (*) as\fpeval{\myxvalue^1000/\myxvalue^999}and does output15. (*) I must improve ;-) – Mar 20 '18 at 14:48 -
@jfbu there are expandable fp to int function. But I can't add it now. – Ulrike Fischer Mar 20 '18 at 14:54
-
-
@Skillmon alternatively to
\ifdimthe etoolbox expandable tests\ifdimcompet al. can serve as wrappers too as you do, until similar user interface gets added toxfp(maybe it is there already??) – Mar 20 '18 at 17:48 -
@UlrikeFischer
\xinttheiexpr ...\relaxwill be very happy to round\fpevallocated inside;-)– Mar 20 '18 at 17:51
The xfp package is wrapper to access at user level the "Floating Point Unit" of LaTeX3. All its operations are expandable.
At the core level they use crucially the e-TeX addition to Knuth TeX of \numexpr, \dimexpr... which allow expandable computations with infix notations (and some sometimes surprising restrictions).
using directly \numexpr/\dimexpr might be all you need.
Maybe you need computations with integers bigger than 2^31 and you want ^operator? and factorial with !? then you can use bnumexpr.
For even more complicated things like add(x(x+1), x=1..100) you can use xintexpr.
An earlier package allowing expandable computations inclusive of powers was intcalc but without infix notations, only macros. Also bigintcalc does it with integers exceeding the 2^31 bound (intcalc achieves expandable computations even if the TeX-engine is lacking e-TeX \numexpr; this is interesting theoretically but quite slower in practice. It does use \numexpr if the latter is available).
As mentioned above xintexpr has extended infix syntax (and is faster when computing with "big" numbers). bnumexpr is a more light-weight package, which hooks also into the core arithmetics provided by xintcore, but does not develop as extensive a syntax as xintexpr.
Naturally at some point you will want to actually store the computations somewhere, via an \edef for example; so the computations are done expandably, without assignments, which is nice for \ifnum, for \write etc... (for embedding in some TikZ things, too), but at end of day you almost always have to do something unexpandable...
Then, things like fp, pgfmath, pgfplots, apnum, are math engine doing things non-expandably to start with (maybe I forget some, please complete). The apnum is arbitrary precision.
As per your original question, perhaps something in this style:
\xintdefvar X := whatever with big integers and fractions;
%
\xintifboolexpr{X^2 + X + 1 < 0}{Yes branch}{No branch}
The first steps does the computations expandably and defines variable X. Then \xintifboolexpr is purely expandable and evaluates X^2 + X + 1 with no assignments.
Of course as was observed by @Skillmon always the No branch is taken here... (there is no interface to complex numbers in xintexpr so far).
-
Even if there were an interface to complex numbers, it doesn’t make much sense to compare complex numbers with zero… ;-) – GuM Mar 20 '18 at 13:54
-
@GuM You aren't completely wrong ;-)... It does make sense, it would expand to yes branch if the complex number is real negative. What does not (with no extra considerations) make sens is to compare two general complex numbers via
<. – Mar 20 '18 at 13:57 -
@GuM If I define the predicate
z<0like I said it behaves correctly with addition, with multiplication by a real positive number, and even by multiplication of two such things if I have also defined similarlyz>0. Hence it does make sense, despite the fact that we prefer that math undergraduate don't read these lines ;-) – Mar 20 '18 at 13:59 -
-
@GuM the key thing is to avoid defining a
z>=0as opposite ofz<0. Because then this new predicate does not behave nicely with respect to addition, contrarily toz<0. Thus to some extentz_1 < z_2may be defined, and alsoz_1 > z_2but it will not be true that eitherz_1 = z_2orz_1 < z_2orz_2 < z_1. – Mar 20 '18 at 14:05
\numexpr\myX*\myX+\myX+1\relax. So in a test this becomes:\ifnum\numexpr\myX*\myX+\myX+1\relax<0(but there is no real value satisfying that inequation). – Skillmon Mar 20 '18 at 12:46