-4
#include <stdio.h>
int main(void)
{
    unsigned sum = 0;
    for (unsigned i = 1; i <= 100000; i++)
    {
        sum += i;
    }
    printf("%lld", sum);
    return 0;
}

Output:705082704

But the correct answer should be 5000050000

July
  • 143
  • 7
  • 1
    How many bits does that value require? How many bits is `unsigned` on your platform? – Retired Ninja Aug 31 '23 at 05:49
  • integer overflow? Check size of the unsigned type with `sizeof(unsigned)`. Your platform probably uses 32 bit unsigned ints, so the biggest value it can hold is `4294967295` (2^32 - 1). The result you're obtaining is 5000050000 % 2^32 due to unsigned overflow – frippe Aug 31 '23 at 05:49
  • `5000050000` > `4294967295` The largest unsigned integer... (And `%lld` is not the right format specifier... which means you're printing rubbish bits...) – Fe2O3 Aug 31 '23 at 05:50
  • @Fe2O3 the `%lld` specifier suggests the OP may be under the impression that `unsigned` _is_ 64-bits. – Chris Aug 31 '23 at 06:00
  • @Chris Can't test with my antique compiler... Is `printf()` expecting to find 8 bytes where there are only 4 (unsigned int)?? – Fe2O3 Aug 31 '23 at 06:02
  • For much larger numbers, consider also using arbitrary precision libraries like [GMPlib](https://gmplib.org/). You'll be able to do integer arithmetics on number with thousands of decimal digits. – Basile Starynkevitch Aug 31 '23 at 06:20
  • Integer numerical limits are typically addressed in the very first chapters of a beginner-level C book. I'd recommend to start there. – Lundin Aug 31 '23 at 06:40
  • Btw surely we must have an integer limit canonical dupe somewhere? Since this would be a FAQ. – Lundin Aug 31 '23 at 06:41

3 Answers3

3

The unsigned integer type on your machine is almost certainly 32-bits. The largest number this type can hold is 4294967295. Your expected result is larger than this, so integer overflow occurs.

The solution is to use a larger data type for sum.

If you include <stdint.h> you might wish to use uint64_t, giving it a max potential value of 18446744073709551615.

As noted by ikegami, you'll also want to provide the correct format specifier when printing a uint64_t value. Typically rather than %lld you'd use %llu. To ensure you get the correct specifier (and there are many) you can include <inttypes.h> and use the PRIuN family of macros. They're listed on the page linked earlier.

E.g.

printf("%" PRIu64 "\n", sum);

If this looks odd to a C beginner, the PRIu64 preprocessor macro inserts the string literal "llu", and neighboring string literals are treated as one continuous string literal by the compiler.

Chris
  • 26,361
  • 5
  • 21
  • 42
  • Seeing as the OP doesn't know how to print an `unsigned int`, perhaps you should mention how to print the `uint64_t` you suggest using? (`#include printf( "%" PRIu64 "\n", sum );`) – ikegami Aug 31 '23 at 06:08
0

The reason for this behavior is unsigned integer overflow. In C, unsigned integer overflow is required to wrap around (but that's not the case for signed integers, though).

Everything seems to point towards the fact that the size of the unsigned type on your machine is 4 bytes, which can store values up to 2^32 - 1 = 4294967295 before it wraps around. You can check the size of a type with sizeof(<the_type>) (i.e., sizeof(unsigned) in your case).

In your case, the largest value of i just before sum overflows is 92681, amounting to an accumulated sum of 92682 * 92681 / 2 = 4294930221 1, which is less than 4294967295. Then you add 98682 and get 4294930221 + 98682 = 4295022903, which cannot fit in an unsigned int on your machine, so it wraps around to 4295022903 % 2^32 = 55607.

Move the print statement into the for-loop to see this in action. You should see something like

.
.
.
4294559503
4294652181
4294744860
4294837540
4294930221
55607
148290
240974
333659
426345
519032
611720
.
.
.

Lastly, note that the result you're getting is equal to 500050000 % 2^32.

ps. You might want to look up format specifiers for printing.


1https://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF
frippe
  • 1,329
  • 1
  • 8
  • 15
-1

As you said "But the correct answer should be 5000050000", but max value of unsigned int is 4294967295, 5000050000 > 4294967295, so unsigned int can not hold the result, you need to use bigger type, such as unsigned long long, max value of this type is 18446744073709551615, which is larger than 5000050000, it can let you get correct result.

When you run the following code:

#include <stdio.h>
#include <limits.h>
int main(void)
{
    unsigned int sum = 0;
    printf("unsigned int max value is %u\n", UINT_MAX);

    unsigned long long  LongSum = 0;
    printf("unsigned long long value is %llu\n", ULLONG_MAX);
    for (unsigned i = 1; i <= 100000; i++)
    {
        LongSum += i;
    }
    printf("%llu\n", LongSum);
    return 0;
}

You will seer the following output, demonstrating the impact of using the two different int types.

unsigned int max value is 4294967295
unsigned long long value is 18446744073709551615
5000050000
Chris
  • 26,361
  • 5
  • 21
  • 42
Tom
  • 417
  • 3
  • 10