Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check that multiplication of two decimal numbers is greater than ULONG_MAX?

Tags:

c++

c

I need to write a function that returns true if the multiplication of two numbers is greater than ULONG_MAX limit. Otherwise returns false.

I tried the following method:

bool isGtThanULONG_MAX(double A, double B) {
    double result = A * B;
    if (result > ULONG_MAX)
        return true;
    else
    {
        //If this could be due to overflow, then again check:
        double temp = result / A;
        
        if (A != 0 && (temp != B)) {
        // overflow handling
        return true;
    }
    return false;
}

}

output: 1st and 4th line in below cout statements are giving OVERFLOW (which is obviously wrong output) and rest are giving NO-OVERFLOW (which is correct) in output. Why it is failing? am I missing anything? please help.

    cout << (isGtThanULONG_MAX(10, 0.0000000000000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;//OVERFLOW
    cout << (isGtThanULONG_MAX(10, 0.000000000000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.00000000000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.0000000000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;//OVERFLOW
    cout << (isGtThanULONG_MAX(10, 0.000000000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.00000000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.0000000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.000000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.00000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.0000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.000000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.00000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.0000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.000001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.00001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.0001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.001) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.01) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 0.1) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;
    cout << (isGtThanULONG_MAX(10, 1) == true ? "OVERFLOW" : "NO-OVERFLOW") << endl;

PS - I tried this program on MS Visual Studio professional 2015 on windows.

like image 978
Jatin Avatar asked May 17 '21 08:05

Jatin


1 Answers

There is a problem if ULONG_MAX cannot be represented exactly as a double. For example if type double uses IEEE representation and long has 64 bits, ULONG_MAX be rounded to the next power of 2 when converted implicitly to double type for the comparison. Hence if this happens, the comparison should be result >= ULONG_MAX to ensure that isGtThanULONG_MAX(0x1p32, 0x1p32) returns true, instead of just > which works for 32-bit longs:

#include <float.h>
#include <limits.h>
#include <stdbool.h>

bool isGtThanULONG_MAX(double A, double B) {
    double result = A * B;
    if (ULONG_MAX + 1.0 == ULONG_MAX)
        return result >= ULONG_MAX;
    else
        return result > ULONG_MAX;
}
like image 133
chqrlie Avatar answered Nov 20 '22 16:11

chqrlie