Tutorial :How can I get the best accurate result?



Question:

Given:

unsigned int a, b, c, d;  

I want:

d = a * b / c;  

and (a *b ) may overflow; also (b/c) may equal zero and give less accuracy.

Maybe a cast to 64-bits would get things to work, but I want to know the best way to get the most accurate result in d.

Is there any good solution?


Solution:1

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

No sense in going to float when you only need more bits. No need to redeclare or cast everything. Casting a is enough to promote b and c to larger size in the expression.


Solution:2

I would either:

  • Cast to 64 bits, if that will work for your ranges of a, b, and c.
  • Use an infinite precision library like GMP
  • Cast to a float or double and back, if you find those results acceptable.


Solution:3

For best accuracy/precision you'll want to do your multiplies before your divides. As you imply, you'll want to use something with twice as many bits as an int:

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

You don't need both casts, but they arguably make it a bit clearer.

Note that if c is small enough, then d can still be bigger than an int. That may or may not be an issue for you. If you're sure it isn't you can cast down to an int at the end.


Solution:4

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


Solution:5

You can always do an explicit check for overflow on a * 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'll also have to check against INT_MIN.

[Update] You could 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);  }  


Solution:6

Why not use a float or double? A float (on intel chips) is a 32-bit floating-point number, so you wouldn't necessarily need 64 bits for the operation?


Solution:7

I'd do something along the lines of the following:

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

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »