Julien Dhondt
Julien Dhondt

Reputation: 13

Non consistent results when calculating the same integer with different expressions

Arithmetic result for the same expression lead to different outcomes depending on wether I define an integer in one line or I use several steps:

int main() {

    unsigned long long veryBigIntOneLine = ((255*256+255)*256+255)*256+255;

    unsigned long long veryBigInt = 255;
    veryBigInt *= 256;
    veryBigInt += 255;
    veryBigInt *= 256;
    veryBigInt += 255;
    veryBigInt *= 256;
    veryBigInt += 255;

    unsigned long long veryBigIntParanthesis = (((((255*256)+255)*256)+255)*256)+255;

    unsigned long long fourthInt = 256;
    fourthInt *= 256;
    fourthInt *= 256;
    fourthInt *= 256;
    --fourthInt;

    cout << "veryBigIntOneLine: " << veryBigIntOneLine << endl;
    cout << "veryBigInt: " << veryBigInt << endl;
    cout << "veryBigIntParanthesis: " << veryBigIntParanthesis << endl;
    cout << "fourthInt: " << fourthInt << endl;

    return 0;

}

they should all describe the same number, 256^4-1 (or 2^32-1), but the outcome is different.

veryBigIntOneLine: 18446744073709551615
veryBigInt: 4294967295
veryBigIntParanthesis: 18446744073709551615
fourthInt: 4294967295

4294967295 is the expected answer (as it is given for all four expressions by the Google calculator).

Also 18446744073709551615 is probably not an exact result of what is computed as I get an overflow warning at compilation time for both one line expressions (even when I tried with type __int128). It is actually 2^64-1, which is the max value for unsigned long long with my compiler (veryBigIntOneLine+1 gives 0).

Upvotes: 0

Views: 67

Answers (2)

Alexis Wilke
Alexis Wilke

Reputation: 20725

This is because you are not using unsigned long long literals. If you want literals to match your definitions you need to use:

255ULL + 256ULL * 255ULL + ...

The ULL is very important if you create numbers that are 64 bits. In C, without the suffix a number may be 64, 32 or even just 16 bits (even bytes on some CRAY where 64 bits. That also means your code would have worked just find on one of those CRAY systems.)

Upvotes: 0

user7860670
user7860670

Reputation: 37478

Initialization code ((255*256+255)*256+255)*256+255 suffers from signed integer overflow which is Undefined Behavior, as well as from implicit conversion of signed int to unsigned. While step-by step calculations avoid those problems because right hand operand is implicitly converted to unsigned long long.

Simply using appropriate literals will fix those issues:

unsigned long long veryBigIntOneLine{ ((255ull*256ull+255ull)*256ull+255ull)*256ull+255ull}; // 4294967295

Upvotes: 2

Related Questions