Suppose we have 2 constants A
& B
and a variable i
, all 64 bits integers. And we want to compute a simple common arithmetic operation such as:
i * A / B (1)
To simplify the problem, let's assume that variable i
is always in the range [INT64_MIN*B/A, INT64_MAX*B/A]
, so that the final result of the arithmetic operation (1) does not overflow (i.e.: fits in the range [INT64_MIN, INT64_MAX]
).
In addition, i
is assumed to be more likely in the friendly range Range1 = [INT64_MIN/A, INT64_MAX/A]
(i.e.: close to 0), however i
may be (less likely) outside this range. In the first case, a trivial integer computation of i * A
would not overflow (that's why we called the range friendly); and in the latter case, a trivial integer computation of i * A
would overflow, leading to an erroneous result in computation of (1).
What would be the "safest" and "most efficient" way to compute operation (1) (where "safest" means: preserving exactness or at least a decent precision, and where "most efficient" means: lowest average computation time), provided i
is more likely in the friendly range Range1.
At now, the solution currently implemented in the code is the following one :
(int64_t)((double)A / B * i)
which solution is quite safe (no overflow) though inaccurate (precision loss due to double significand 53 bits limitation) and quite fast because double division (double)A / B
is precomputed at compile time, letting only a double multiplication to be computed at runtime.