# A bug with high precision

Consider the following two numbers:

num1=0.0006000000000000001;
num2=0.0006000000000000003;


num2 appeared from num1 as a result of some compiled code with RuntimeOptions->"Speed".

Their direct comparison returns

num1==num2


True

However,

{num1, num2} // DeleteDuplicates


keeps both the numbers.

Why do these two operations work at different precision levels?

P.S. Mathematica 13.2 on Windows 11.

• To be clear, this is not a bug. Commented Feb 19 at 3:17
• @DanielLichtblau : formally, yes. But in practice, I spent a lot of time trying to uncover errors in my code because of this mismatch. Commented Feb 19 at 11:12

## 3 Answers

Because default DeleteDuplicates uses === and not == (i.e SameQ). (unless overriden)

You can see this

num1 = 0.0006000000000000001;
num2 = 0.0006000000000000003;
DeleteDuplicates[{num1, num2}, (#1 === #2) &]


Which is same as

DeleteDuplicates[{num1, num2}]


But

DeleteDuplicates[{num1, num2}, (#1 == #2) &]


SameQ checks the two objects are identical in the sense that they occupy same memory location they have identical FullForm

While for ==

So when comparing numbers, use == and when comparing symbolic expressions use ===

• @"SameQ checks the two objects are identical in the sense that they occupy same memory location" Not quite following the reasoning behind this statement, but I'd say that is not the case. Commented Feb 18 at 16:02

From the help of Equal ( "==" ): "Numbers with machine precision (MachinePrecision) or greater are considered equal if they differ in at most their last seven binary digits."

As Nasser already mentioned, "DeleteDuplicates" uses "SameQ". From the help of "SameQ": "SameQ requires exact correspondence between expressions, except that it still considers Real numbers equal if they differ in their last binary digit."

Now, as "==" is less strict than "===" you get:

num1 == num2

True


and

num1 === num2

False


Finally, consider the binary representation of num1 and num2 (note that $MachinePrecision on my machine is:15.954589770191003 ) num1 = 0.000600000000000000115.954589770191003; num2 = 0.000600000000000000315.954589770191003; BaseForm[num1, 2] BaseForm[num2, 2]  As you see, the numbers differ in the last 3 digits. • Nice. You need to copy and paste result of$MachinePrecision to see the full value. Commented Feb 18 at 23:14

Warning!!! If you evaluate this your believe in logical reasoning may be ruined ;-)

n1 = 0.59999999999999993;
n2 = 0.6000000000000001;
n3 = 0.6000000000000002;

{n1 == n2 == n3}
{n1 === n2, n2 === n3, n1 === n3}


{True}
{True, True, False}

Clue:

Real numbers are considered SameQ if they differ only in their last binary digit
(the statement is not phrased well, it should be understood so that they can differ by +/- 1 least significant bit)

RealDigits[n1, 2]
RealDigits[n2, 2]
RealDigits[n3, 2]

• This is why it's important to be aware of multi-arg SameQ: n1 === n2 === n3 (*False*). SameQ isn't always transitive when it comes to numerical quantities and the multi-arg use case can account for this. Commented Feb 19 at 12:22
• @Sjoerd Smit: It is not property of SameQ alone, it is similar with Equal used on reals numbers. Commented Feb 19 at 12:40