Home > Software design >  Unexpected result in long int division of C
Unexpected result in long int division of C

Time:10-21

I try to make a long int division in C, but I can't get the correct result. I'm curious about the reason why I got the crash and how can I get the correct result.

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

int main() {
    int64_t a = 0x8000000000000000;
    int64_t b = 0xffffffffffffffff;
    printf("a: %ld; b: %ld\n", a, b);
    int64_t c = a/b;
    printf("a/b: %ld\n", c);
    return 0;
}

Here is the result:

(base) ➜  ~ gcc test.c -O2
(base) ➜  ~ ./a.out
a: -9223372036854775808; b: -1
a/b = : -9223372036854775808
(base) ➜  ~ gcc test.c
(base) ➜  ~ ./a.out
a: -9223372036854775808; b: -1
[1]    39193 floating point exception (core dumped)  ./a.out

Result of the division

CodePudding user response:

First, try using the right format specifiers. Include inttypes.h and use printf(PRId64 "\n", x); to print int64_t x;. %ld is not portable. It might work and might not.

Then note that the answer of the division int64_t c = a/b; would be 2^63 if the integers weren't limited in size. But in fact there is no representation for that number using 64-bit 2's complement numbers. They range from -2^63 to 2^63 - 1. That's what's causing the exception. You've overflowed the arithmetic unit that's doing the division.

Open your textbook to study up on binary integer representation.

CodePudding user response:

As you already noticed, printing a and b:

int64_t a = 0x8000000000000000;
int64_t b = 0xffffffffffffffff;
printf("a:%" PRId64 ", b:%" PRId64 "\n", a, b);

Yields the following:

a:-9223372036854775808, b:-1

However, dividing 64-bit signed integer INT64_MIN by -1 on a 64-bit machine is an undefined behaviour.

A horrible artifact of two's complement arithmetic is the 'most negative number' problem. Take this code:

int8_t a = -127; //-127 to 127 OK
int8_t b = -1;
printf("a/b: %hhd\n", a/b);

This code will work for any value of a, except for -128 (INT8_MIN). That's because:

1000 0000 (-128)
0111 1111 (bit flip)
1000 0000 (add one, back at -128!!)

But actually if you look at the second last step:

0111 1111 (bit flip)

If you add one to that, we have already overflowed, because the first bit is reserved as a sign bit.

  •  Tags:  
  • c
  • Related