The code is right. And standard compliant. I changed the WriteLine
line to this :
Console.WriteLine($"{sum:0.000} {value:0.000} {division:N18} - {result:0.00000}");
And got
2.105 0.526 4.000000000000000000 - 4.00000
2.632 0.526 5.000000000000000000 - 5.00000
3.158 0.526 5.999999523162841797 - 5.00000
3.684 0.526 6.999999523162841797 - 6.00000
4.211 0.526 7.999999046325683594 - 7.00000
4.737 0.526 8.999999046325683594 - 8.00000
Rounding errors mean the division result isn't exactly 6, 7 or 8. With just 5 digits, I get:
3.158 0.526 6.00000 - 5.00000
3.684 0.526 7.00000 - 6.00000
4.211 0.526 8.00000 - 7.00000
4.737 0.526 9.00000 - 8.00000
This isn't about how C# truncates or rounds, it's about how floating point numbers are formatted. The IEEE compliant way is to round to the desired precision when formatting.
Phew - for a moment, I actually forgot what I knew about floats.
PS: there's another funny change at 15 digits that was introduced in .NET Core 3. Before that, string formatting stopped producing digits at 15 digits which lead to quite a bit of confusion with values that were close but not quite equal to an integer.
Since .NET Core 3, the string formatter emits enough digits to produce the shortest roundtrippable string
. Using
Console.WriteLine($"{division} - {result}");
Produces :
4 - 4
5 - 5
5.9999995 - 5
6.9999995 - 6
7.999999 - 7
8.999999 - 8
Which is why they teach us in computing math to never compare floats for equality, but only check whether the absolute difference is below a threshold.
Something I always forget and have to rediscover after crashes or infinite loops.
PPS: Rounding errors
The fractional digits are produced because float
doesn't have enough precision to store either sum
or division
without rounding.
Using $"{sum} {division} - {result}"
and switching from float
to double
produces only one result with fractional digits:
3.1578948 6 - 6
3.6842105999999997 6.999999999999999 - 6
4.2105264 8 - 8
Notice that even sum
has rounding errors.
Only decimal
has enough precision to store an accurate result and avoid rounding errors:
2.63157900 5 - 5
3.15789480 6 - 6
3.68421060 7 - 7
4.21052640 8 - 8
4.73684220 9 - 9