> But I do think that this is more a quirk on how operators are done specifically in C and not a general matte
That has nothing to do with C, but with the CPU and its registers. x86 has 80bit floating point registers (too), so if the compiler/CPU (doesn't matter which language) saves a value in a 80 bit floating point register and moves it from there to memory where it is stored in 64 bits, the number gets rounded (not truncated, it's actually converted).
See also the GCC page:
For instance, in the following code segment, depending on the compilation
flags and numbers and calculations used to find tmp, the following code may
print out that the values are different:
double tmp, X[2];
tmp = ....
tmp += ....
...
X[0] = tmp;
if (X[0] == tmp)
printf("Values are the same, as expected!\n");
else
printf("Values are different!\n");
This is because tmp will typically be moved to a register during register
assignment, which means tmp may hold a full 80 bits of accuracy, some of
which are lost in the store to X[0], and thus the numbers are no longer
equal. You may workaround this problem by always explicitly storing to
memory to force the round-down.
> Are the comparison and arithmetic operations considered to be contracted in these sort of situations?
No. Or well, maybe. 'Contracted' means using e.g. FMA (fused multiply and add), so addition and multiplication like `ab + c` is done in a single step instead of two. Which means that the result is only rounded once (`ab + c` is rounded), whereas without this fusing/contracting `ab` would be rounded and `ab + c` would be rounded again (actually depending on the optimization/compiler flags). So the results (may) differ.
That has nothing to do with C, but with the CPU and its registers. x86 has 80bit floating point registers (too), so if the compiler/CPU (doesn't matter which language) saves a value in a 80 bit floating point register and moves it from there to memory where it is stored in 64 bits, the number gets rounded (not truncated, it's actually converted).
See also the GCC page:
https://gcc.gnu.org/wiki/x87note> Are the comparison and arithmetic operations considered to be contracted in these sort of situations?
No. Or well, maybe. 'Contracted' means using e.g. FMA (fused multiply and add), so addition and multiplication like `ab + c` is done in a single step instead of two. Which means that the result is only rounded once (`ab + c` is rounded), whereas without this fusing/contracting `ab` would be rounded and `ab + c` would be rounded again (actually depending on the optimization/compiler flags). So the results (may) differ.