-1

I've read a few posts and I understand how double arithmetic doesn't always return the results you would expect.

Why is floating point arithmetic in C# imprecise?

My problem is different though because I'm checking to see if two numbers are the same and I'm getting false when I would expect true.

I've also read this What Every Computer Scientist Should Know About Floating-Point Arithmetic, but am still having trouble understanding why two seemingly equal double variables are showing unequal.

enter image description here

UPDATE: They answer below helped me understand that the value displayed by the debugger wasn't the 'whole story'. That is why the two floats seemed equal. The debugger was showing equal values when hovering the variables.

enter image description here

Community
  • 1
  • 1
Neil B
  • 2,096
  • 1
  • 12
  • 23
  • 3
    Try using `Decimal` instead. – Blue May 07 '19 at 02:35
  • What's `itme` ? – D-Shih May 07 '19 at 02:40
  • Both qty1 and item.Length are doubles. – Neil B May 07 '19 at 02:43
  • 1
    Because they are `seemingly equal double`, but not truly equal – Backs May 07 '19 at 02:45
  • 1
    What is your question? I dont see any – Backs May 07 '19 at 02:46
  • `why two seemingly equal double` you keep on answering your own question, they only seem equal. and when you realise that, you will realise you cannot do these sort of operations happily and expect happy results. you need to account for rounding errors up to x decimal places , or use a type that can store decimals more appropriately in base 10 ' – TheGeneral May 07 '19 at 02:49
  • Use round-trip representation when converting `double` to `string`: `qty1` -> `qty1.ToString('R')`, `item.Length` -> `item.Length.ToString('R')`. – user4003407 May 07 '19 at 03:10
  • are you using a 32-bit build? then one value might be in the x87 register with higher precision and another in double precision – phuclv May 07 '19 at 03:44

1 Answers1

1

Default string format is not precise for float numbers, should use "G17"

double a = 17.125 / 3.0;
double b = 17.12499999999999 / 3.0;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(a.ToString("G17"));
Console.WriteLine(b.ToString("G17"));
Console.WriteLine(a == b);
Console.WriteLine(Convert.ToString(*(long*)&a, 2));
Console.WriteLine(Convert.ToString(*(*)&b, 2));

Result:

5.70833333333333
5.70833333333333
5.708333333333333
5.7083333333333295
False
100000000010110110101010101010101010101010101010101010101010101
100000000010110110101010101010101010101010101010101010101010001

Usually to compare 2 float numbers, you can use a small error number

Console.WriteLine(Math.Abs(a - b) < 0.0000001);
shingo
  • 18,436
  • 5
  • 23
  • 42