I wrote a simple program that sums the square of integers m -> n. If sum is declared as double it gives something like 4.16..x10^10 for integers 1 -5000. However, if sum is declared as an int, for the same range it reports -1270505460.

Obviously this has something to do with the 4-bytes allocated for int, but vague intuition != explanation. Can someone give me a good explanation for this phenomenon?

Dani AI

Generated

Brief, concrete explanation plus fixes relevant to the posts by , , , and .

The exact sum of squares for 1..5000 is
5000·5001·10001/6 = 41,679,167,500. That value does not fit in a 32‑bit signed int, so the stored bit‑pattern seen on typical platforms corresponds to a negative signed value. The closed form is the square‑pyramidal formula. (en.wikipedia.org)

C++ semantics: unsigned integer arithmetic is defined to operate modulo 2^n, while signed integer overflow is undefined behaviour — the standard does not guarantee wrap‑around. On most common implementations (two’s‑complement machines and mainstream compilers) overflowing a signed int appears to “wrap”, which is why the negative result was observed; but relying on that is non‑portable and unsafe. (cppreference.net)

How the exact negative value appears (modular view):
41,679,167,500 mod 2^32 = 3,024,461,836.
Interpreted as a 32‑bit signed integer that value equals 3,024,461,836 − 2^32 = −1,270,505,460,
which matches the reported −1270505460. This is why ’s “loop” description matches common behaviour, and why ’s warning about assuming sizes is important. (cppreference.net)

Practical fixes:

  • Use a wider fixed type (int64_t / long long) when sums can exceed 32‑bit; the <cstdint> header documents fixed‑width types. (en.cppreference.com)
  • For arbitrarily large sums, use a multiprecision library (e.g., Boost.Multiprecision). (beta.boost.org)

Example (safe for this case; adjust for portability as needed):

#include <cstdint>
#include <iostream>

int main() {
    int64_t n = 5000;
    __int128 t = (__int128)n * (n + 1) * (2*n + 1);
    int64_t sum = (int64_t)(t / 6);
    std::cout << sum << '\n'; // 41679167500
}

Notes: __int128 is a common compiler extension used here to avoid intermediate overflow; for full portability and arbitrarily large values prefer boost::multiprecision::cpp_int. (beta.boost.org)

Recommended Answers

All 14 Replies

This is because of the size limitations of data types.

an int is only 4 bytes...and has a range from -2,147,483,648 to 2,147,483,647

A double uses 8 bytes (and some floating point algorithm that is beyond my comprehension at the moment) and has a range from +/-1.7E-308 to +/-1.7E308.

Your number simply went out of the range of an integer.

Interestingly enough...integers will simply loop through thaie cycle...i.e. if the number is larger than 2,147,483,647 it will restart the count at -2,147,483,648...whild doubles that exceed their upper limit will cause an error.

If sum is declared as double

Why would you declare sum as double in first place?
You can use long and it's variations.

sum is declared as an int, for the same range it reports -1270505460.

If int( or any other type) cannot accomodate the data then results are unpredictable.

This is because of the size limitations of data types.

an int is only 4 bytes...and has a range from -2,147,483,648 to 2,147,483,647

A double uses 8 bytes (and some floating point algorithm that is beyond my comprehension at the moment) and has a range from +/-1.7E-308 to +/-1.7E308.

Your number simply went out of the range of an integer.

Interestingly enough...integers will simply loop through thaie cycle...i.e. if the number is larger than 2,147,483,647 it will restart the count at -2,147,483,648...whild doubles that exceed their upper limit will cause an error.

Don't make any assumptions about size of types. Standard only guarantees minimum sizes.

True...the data types and sizes shown are typical on Windows systems, and the sizes and ranges may be different on other operating systems...

You can determine the size of an integer using sizeof(int); .

Still...my explanation is the most plausable...he has simply exceeded to range of an int.

Instead of double use long long.

If you are working with C++ and your application really demands high precision and range why not try out some third party libraries like these:

http://www.nongnu.org/hpalib/

Though these libraries require you to study them before you use them, they are worth the effort.

HOpe it helped, bye.

Instead of double use long long.

Only if he's using C or C99 to be more specific.

I think we lost track of the question...

He wanted to know WHY this happened using an int...not alternatives to using an int.

Straight from the textbook...

When a variable is assigned a number that is too large for its data type, it overflows. Likewise, assigning a value that is too small for a variable causes it to underflow.

Typically, when an integer overflows, its contents wrap around to that data type's lowest possible value...

Also...it you want to get your doubles to print as numbers instead of E notation, use cout << fixed;

I think we lost track of the question...

Very common situation in forums :)

Only if he's using C or C99 to be more specific.

Sorry but I'm always asuming that using C and C99 don't know why. Probably becouse i'm using it


Interestingly enough...integers will simply loop through thaie cycle...i.e. if the number is larger than 2,147,483,647 it will restart the count at -2,147,483,648...whild doubles that exceed their upper limit will cause an error.

Perfect -- I was just looking for a correct explanation .

Man...my spelling really blew chunks on that one...lol

I need to learn to proof-read before I hit post!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.