# IntegerPart - is this a known bug?

I'm working in Mathematica 13.0 and I type

a=0.00001;
IntegerPart[a/a]


and well, the output is 0.

Try with almost any other value of a, say a=0.01, and the result is correctly 1. I did some trials and I found that it fails again with a=0.000000001. I also found that a possible fix is

a=0.00001 // Rationalize;


(then I got tired). What is going on? Can this have to do with the MachinePrecision?

More in general, how do I fix it once and for all for the entire Notebook?

• RealDigits[a/a] => {{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}, 0} In the memory this is a number less than 1. Yes it has to do with machine epsilon Commented Aug 8, 2022 at 14:31
• Also interesting example: arr = RandomReal[1, 100000]; Tally[RealDigits /@ (arr/arr)] => {{{{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}, 0}, 15338}, {{{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1}, 84662}}. ~15% numbers giving not 1 when you try to divide number on itself Commented Aug 8, 2022 at 14:38
• Try IntegerPart[Divide[a, a]]. It has been noted before on this site that "a / a" is parsed as Times[a, Power[a, -1]]. The roundoff error in 1 / a = 99999.99999999999 means a * (1/a) does not cancel (and sometimes doesn't for other values of a). Commented Aug 8, 2022 at 14:42
• @KirillBelov You might be interested in this: Table[a = 10.16^-k; IntegerPart[a/a], {k, 100}]. The use of arbitrary-precision means more bits than in machine precision are used to represent the floating-point numbers (plus precision tracking, which is unimportant here). All the extra precision does is change where the problem occurs. Commented Aug 8, 2022 at 14:58
• See also this and this. Commented Aug 9, 2022 at 4:31

[H]ow do I fix it once and for all for the entire Notebook?

I suppose it depends on how you want to treat results that contain round-off error. You cannot really get rid of the problem, only shift where the problem arises. For instance, in IntegerPart[x], IntegerPart (nor usually the program/programmer) knows at that point whether the roundoff error that led to x is positive, negative, or zero. If you fix IntegerPart[x] when x comes from a/a and is one bit less than 1., then it will be broken when another x has a roundoff error that increases it to one bit less than 1.. One may be willing to live with it being broken in this way. Here's a way based on Equal comparing with tolerance:

intPart // ClearAll;
intPart[x_?NumericQ] /; x == Round[x] := Round[x];
intPart[x_?NumericQ] := IntegerPart[x];

intPart[a/a]
(*  1  *)


Make it Listable if your code relies on IntegerPart being listable. You can change the tolerance used by Equal with Internal\$EqualTolerance.

Another approach is to "correct" real numbers that are close to integers:

snapToInteger // ClearAll;
snapToInteger[expr_] :=
expr /. {x_Real /; x == Round[x] :>
SetPrecision[Round[x], Precision[x]]};

IntegerPart[snapToInteger[a/a]]
(*  1  *)


Either approach is likely to incur a performance hit, which may or may not be important.

For what it's worth, this works on x = a/a, because of the nature of the rounding error and how MatchQ works on machine reals and bignums, and it's a bit faster:

intPart // ClearAll;
intPart[x_Real] /; MatchQ[x, N[Round[x], Precision[x]] :=
Round[x];
intPart[x_?NumericQ] := IntegerPart[x];

• I have to say that using Divide[a/a], as you suggested under my question, is also (often) a quick and valid fix. Commented Aug 10, 2022 at 9:10
• @DavideVenturelli You may have noticed that if x is a symbol (without a numeric or other value), Divide[x, x] evaluates to x/x, that is, Times[x, Power[x, -1]]. Sometimes it's not so easy to replace / by Divide[], and since there was no response to my comment, I thought it might not work in all your use-cases. Commented Aug 10, 2022 at 13:18