1

I tried to print the result of 99,999 * 99,999 * 99,999, the result should have been 999,970,000,299,999 but what got printed instead was 18446744072244127711. I tried to print 20000 * 20000 * 20000 and the result was pretty much the same. Can you guys tell me how to get the real result?

#include <stdio.h>

int main()
{
    int num;

    printf("Insert number : ");
    scanf("%ld", &num);

    fflush(stdin);

    unsigned long long int total = num * num * num;
    printf("Result : %llu", total);

    getchar();
    return 0;
}
Student
  • 805
  • 1
  • 8
  • 11
Kenny
  • 17
  • 5

2 Answers2

4

One way to do it is:

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>

int main(void)
{
    uint64_t x = 99999;
    printf("%" PRIu64 "\n", x*x*x);
}

You may also be able to do this with unsigned long or unsigned long long types, but these depend on your C implementation (the compiler you are using).

The arithmetic you attempted overflowed the supported range of the int type you were using. When programming, it is important to ensure that the calculations you do will not overflow the range of the types you use.

Additionally, you must be careful about types in C code:

  • When using scanf, match the conversion specifier to the type. For example, when scanning a decimal numeral for an int object, you should use %d, not %ld. %ld is for long int.

  • In unsigned long long int total = num*num*num;, the unsigned long long int affects the type of total. It does not affect the type used in the calculation num*num*num. In that expression, the type of num is used. To use unsigned long long int in the calculation, you would have to convert one or all of the operands to unsigned long long int, as by using a cast: (unsigned long long int) num * num * num.

  • By assigning 99999 to a uint64_t object, which I named x, I ensured that x*x*x was calculated with uint64_t arithmetic. (uint64_t is a 64-bit unsigned integer.) Another way to do this would be with UINT64_C(99999) * UINT64_C(99999) * UINT64_C(99999). UINT64_C is a macro defined in stdint.h that essentially means “treat this constant as having type uint64_t or wider (actually uint_least64_t).” This could also be done with UINT64_C(99999) * 99999 * 99999 because C will automatically convert the narrower-type integer operands to the wider-type integer operand. It could also be done with (uint64_t) 99999 * 99999 * 99999.

  • PRIu64 is a macro that provides the right printf conversion specifier for uint64_t. It is defined in inttypes.h.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Pedantically, `UINT64_C` gives a literal of type `uint_least64_t` and not `uint64_t`. – Lundin Feb 21 '18 at 14:57
  • Nice answer (as always). But I would make it clear that `(unsigned long long int) num * num * num` is only casting the first coefficient. The other two are implicitly converted. – Bathsheba Feb 21 '18 at 15:20
3

Bugs:

  • %ld on an int invokes undefined behavior.
  • fflush(stdin) invokes undefined behavior since stdin is an input stream.
  • num*num*num is carried out on operands that have type int, so you get overflow if you attempt 99999 * 99999 * 99999 since this is a larger number than 231-1 (assuming 32 bit int).

Fixed code:

#include <stdio.h>

int main(void)
{
    int num;
    printf("Insert number : ");
    scanf("%d",&num); getchar();
    long long int total = (long long)num*num*num;
    printf("Result : %llu",total);
    getchar();
    return 0;
}
Lundin
  • 195,001
  • 40
  • 254
  • 396