is there no floating point error on a / b == ka / kb?
Assuming IEEE-754 binary floating-point arithmetic is used with the round-to-nearest-ties-to-even rule, the comparison is true except in the cases below.
Given int
num1
, num2
, num3
, and num4
where num3
= k • num1
and num4
= k • num2
for some real number k, there are the following situations where static_cast<double>(num1) / num2 == static_cast<double>(num3) / num4
may evaluate to false:
num3
andnum4
are both zero, either becausenum1
andnum2
are zero or because k is zero. Thenstatic_cast<double>(num3) / num4
evaluates to a NaN, and a NaN never compares equal to anything, not even to the same NaN.num2
is zero butnum1
is not and k is negative. Thenstatic_cast<double>(num1) / num2
evaluates to +∞ or −∞ according to whethernum1
is positive or negative, whilestatic_cast<double>(num3) / num4
evaluates to the opposite, −∞ or +∞ respectively, so the comparison evaluates to false.- When
int
, excluding the sign bit, is wider than the significand ofdouble
, the quotients may differ due to different roundings in the conversion todouble
. For example,int
may be 64 bits whiledouble
has a 53-bit significand. Supposenum1
is 253+1,num2
is 1, and k is 3, sonum3
is 254+253+2+1 andnum4
is 3. Then, due to rounding,static_cast<double>(num1)
produces 253,static_cast<double>(num3)
produces 254+253+4, and the divisions produce 253 and 253+2, which are not equal. - In cases where k •
num1
or k •num2
overflows theint
type, the comparison may evaluate to false.
Other than in the cases above, the conversions to double
are exact, and the quotients are mathematically defined (do not have zero divisors) and are equal. In these cases, the rounding rule necessitates that the two divisions produce the same result, so the comparison evaluates to true.
Yes, you can get different answers; even when there are no NaN
/Infinity
etc. values are around. See Eric's fantastic answer as usual for the details. Here's a concrete counter-example to illustrate:
#include <stdint.h>
#include <stdio.h>
int main()
{
int32_t k = 1097303040;
int32_t a = 536913409;
int32_t b = 2097152;
double lhs = static_cast<double>(a) / b;
double rhs = static_cast<double>(k*a) / (k*b);
printf ("k = %d\n", k);
printf ("a = %d\n", a);
printf ("b = %d\n", b);
printf ("lhs = %f\n", lhs);
printf ("rhs = %f\n", rhs);
printf ("equal: %d\n", lhs == rhs);
return 0;
}
When run, this program produces:
k = 1097303040
a = 536913409
b = 2097152
lhs = 256.020264
rhs = -0.757798
equal: 0
Note that the results are not only not equal, they even have different signs!