Asil
Asil

Reputation: 884

C++ is giving different wrong results for same arithmetic expression

I have a very simple calculation where I calculate the distance between each individual cell to center in a 2D space. I know that the O(n) solution is redundant and I derived the formula for O(1) solution. But what I am trying to understand is: Why do these two analogous calculations give me two different results?

Here is the expected (correct) result in Python (Both versions give the same result):

result = 0;
n = 499993;
center = (n+1)//2;
for ii in range(1,center):
        result += (ii*ii*8);

print(result);

which outputs:

41664916690999888

And here are two versions in C++ with two completely different wrong results:

1)

#include <iostream>
using namespace std;
int main()
{
    unsigned long long result = 0;
    int n = 499993;
    int center = (n+1)/2;
    for(int ii = 1; ii < center; ++ii)
    {
        result += (ii*ii);
    }
    cout << result*8 << endl;
}

Output:

154435732281936
#include <iostream>
using namespace std;
int main()
{
    unsigned long long result = 0;
    int n = 499993;
    int center = (n+1)/2;
    for(int ii = 1; ii < center; ++ii)
    {
        result += (ii*ii*8);
    }
    cout << result << endl;
}

Output:

6229295798864 

What is the reason of this behavior?

For compiler I am using GCC with only -g flag

Online compiler for CPP that produces the same result: https://www.onlinegdb.com/online_c++_compiler

Thanks in advance!

Upvotes: 1

Views: 439

Answers (1)

MikeCAT
MikeCAT

Reputation: 75062

Typical int (signed 32bit) can store only upto 2,147,483,647 (2**31 - 1).

The calculation of ii*ii will exceed this limit when ii becomes larger than 46340.

You are using unsigned long long for result, so casting to that before calculation will improve the behavior.

#include <iostream>
using namespace std;
int main()
{
    unsigned long long result = 0;
    int n = 499993;
    int center = (n+1)/2;
    for(int ii = 1; ii < center; ++ii)
    {
        result += (static_cast<unsigned long long>(ii)*ii); // add casting
    }
    cout << result*8 << endl;
}

Upvotes: 3

Related Questions