How can I get the best accurate result?

Given:

unsigned int a, b, c, d;

      

I want to:

d = a * b / c;

      

and (a * b) may overflow; also (b / c) can be zero and give less precision.

Maybe casting to 64-bits will work, but I want to know how best to get the most accurate result in d.

Is there a good solution?

0


a source to share


7 replies


For your problem as stated, I would do d = (long long)a * b / c;



It makes no sense to go in float

when you need more bits. No need to change clothes or leave everything. Casting is a

enough to advance b

and c

to a larger size in expression.

+1


a source


I would like to:



  • Paste up to 64 bits if that would work for your a, b and c ranges.
  • Use an infinite precision library like GMP
  • Head to float

    or from double

    and back if you find these results acceptable.
+5


a source


For best precision / precision, you want to do your multiplications before your divisions. As you imply, you will want to use something twice as large as an int:

int64_t d = (int64_t) a * (int64_t) b;
d /= c;

      

You don't need both throws, but they might make it clearer.

Note that if c is small enough, then d can still be larger than int. This may or may not be a problem for you. If you are sure that it is not you can reset to the end at the end.

+3


a source


Use float or double, in floating point arithmetic, division by zero is allowed , results will be positive or negative infinity

+1


a source


You can always do an explicit overflow check on * b:

long long e = (long long) a * (long long) b;
if (e <= INT_MAX) {
    d = e / c;
} else {
    d = a * (b / c);
}

      

Of course, this only works for non-negative a, b, c. If they can be negative, you will need to check INT_MIN as well.

[Update] You can also check which of a and b is larger, and thus loses less precision when divided by c:

if (a >= b) {
    d = a / c * b;
} else {
    d = a * (b / c);
}

      

+1


a source


Why not use float

or double

? A float

(on Intel chips) is a 32-bit floating point number, so the operation doesn't necessarily need 64 bits?

0


a source


I would do something along the following lines:

if(c){
    d = (long long)a * b;
    d /= c;
}
else{
    // some error code because div by 0 is not allowed
}

      

0


a source







All Articles