Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this multiply-divide function correct?

I'm trying to avoid long longs and integer overflow in some calculations, so I came up with the function below to calculate (a * b) / c (order is important due to truncating integer division).

 unsigned muldiv(unsigned a, unsigned b, unsigned c)
 {
      return a * (b / c) + (a * (b % c)) / c;
 }

Are there any edge cases for which this won't work as expected?

like image 987
Electro Avatar asked Feb 20 '23 17:02

Electro


1 Answers

EDITED: This is correct for a superset of values for which the original obvious logic was correct. It still buys you nothing if c > b and possibly in other conditions. Perhaps you know something about your values of c but this may not help as much as you expect. Some combinations of a, b, c will still overflow.

EDIT: Assuming you're avoiding long long for strict C++98 portability reasons, you can get about 52 bits of precision by promoting your unsigned to doubles that happen to have integral values to do the math. Using double math may in fact be faster than doing three integral divisions.

like image 59
Mark B Avatar answered Mar 06 '23 01:03

Mark B