Consider the following C # code:
double result1 = 1.0 + 1.1 + 1.2; double result2 = 1.2 + 1.0 + 1.1; if (result1 == result2) { ... }
result1 should always equal result2 right? The fact is that no. result1 is 3.3, and result2 is 3.000000000000003. The only difference is the order of the constants.
I know that doubles are implemented in such a way that rounding problems can occur. I know that I can use decimals if I need absolute precision. Or that I can use Math.Round () in an if statement. I'm just a nerd who wants to understand what the C # compiler does. Can anyone tell me?
Edit:
Thanks to everyone who has so far offered to read on floating point arithmetic and / or talked about the inherent inaccuracy of the processor doubling. But I feel that the main question of my question still remains unanswered. What is my fault for its incorrect formulation. Let me say the following:
Having interrupted the above code, I would expect the following operations:
double r1 = 1.1 + 1.2; double r2 = 1.0 + r1 double r3 = 1.0 + 1.1 double r4 = 1.2 + r3
Suppose that each of the above additions has a rounding error (with the number e1..e4). Thus, r1 contains the rounding error e1, r2 includes the rounding errors e1 + e2, r3 contains e3 and r4 contains e3 + e4.
Now I don’t know exactly how the rounding error occurs, but I would expect e1 + e2 to be equal to e3 + e4. It is clear that this is not so, but it seems to me somehow wrong. Another thing is that when I run the above code, I don't get rounding errors. This makes me think that the C # compiler is doing something weird, not a processor.
I know that I ask a lot, and maybe the best answer anyone can give is to go do a PHD in the processor design, but I just thought I'd ask.
Edit 2
Looking at IL from my source code sample, it’s clear that this is a compiler, not a processor that does this:
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint .maxstack 1 .locals init ( [0] float64 result1, [1] float64 result2) L_0000: nop L_0001: ldc.r8 3.3 L_000a: stloc.0 L_000b: ldc.r8 3.3000000000000003 L_0014: stloc.1 L_0015: ret }
The compiler adds numbers for me!