Compare two whole products without overflow

I need to find if there are 32-bit integers ('int' on my machine) a*b >= c*dwhere a,b,c,dsigned.

Can these products be compared using only 32-bit integers without overflow so that the result is correct for all possible values?

I was thinking about a/d >= c/b.

However, it does not work on '2 * 7> = 3 * 5' (false), because '2/5> = 3/7' ('0> = 0') is true.

+4
source share
3 answers

At the moment, I'm going to assume that the inputs are signed integers.

. , , (, , ), .

, , , .

, , 32- , , - . , a, b, c d 16 . , :

al = a & 0xffff;
au = a >> 16;

bl = b & 0xffff;
bu = b >> 16;

:

a * b 

... - , :

(al + au << 16) * (bl + bu << 16)

, :

al * bl + au<<16 * bl + al * bu<<16 + au<<16 * bu<<16

a * (b * c)= (a * b) * c, - , :

al * bl +            // we'll call this intermediate result "lower"
(au * bl) << 16 +
(al * bu) << 16 +    // we'll call the sum of these two "mid" 
(au * bu) << 32      // we'll call this one "upper"

: , , 16 , 32 , 32- .

. , . -, , . :

bool carry(unsigned a, unsigned b) { 
    return a > (std::number_limits<unsigned>::max() - b);
}

+ < 16 + < 32. 32- , mid . ​​ lower, - upper. ( ) 32- , lower + mid_lower, - upper + mid_upper + carries.

, , , , .

, , .

+5

1

bigint. Boost .

#include <boost/multiprecision/cpp_int.hpp>
bool BigintCompareProducts(int a, int b, int c, int d)
{
  using boost::multiprecision::cpp_int;
  return cpp_int(a) * cpp_int(b) >= cpp_int(c) * cpp_int(d);
}

2

a/d >= c/b, . , .

// Returns 1, 0, or -1 if a is >, ==, or < b
template<typename T>
int cmp(T a, T b)
{
  return a > b ? 1 : (a < b ? -1 : 0);
}

// Returns 1, 0, or -1 if n1/d1 is >, ==, or < n2/d2
int CompareFractions(int n1, int d1, int n2, int d2)
{
  int f1 = n1 / d1;
  int f2 = n2 / d2;
  int result = cmp(f1, f2);
  if (result != 0) {
    return result;
  }

  // Equal fractions - remainder may make them different
  int r1 = n1 % d1;
  int r2 = n2 % d2;
  if (r1 == 0 || r2 == 0) {
    // Any zero remainder is less than any positive fraction.
    return cmp(r1, r2);
  } else {
    return -1 * CompareFractions(d1, n1 % d1, d2, n2 % d2);
  }
}

// Returns 1, 0, or -1 if a * b >, ==, or < c * d
int CompareProducts(int a, int b, int c, int d)
{
  return CompareFractions(a, d, c, b);
}
0

Not sure if this fits your needs, but you should try:

int a, b, c, d;
// set them for a*b=c*d

int one = a/d, two = c/b
int greatest = one;
if (two > greatest) greatest = two;
int k = pow(10.0, 8-log(greatest)); // log (INT_MAX) = 9

one = k*a/d;
two = k*c/b;

// if one > two then a*b > c*d

For 2 × 7> = 3 × 5, you got 40,000,000> = 42857142, so it is false as intended.

0
source

All Articles