Comment

Comment by mokus

The title is actually wrong - the -O0 version is correct, the -O3 version is not (despite giving the output the author expected).

Casting the value to double ends up converting the long value 0x7fffffffffffffff to the nearest double value: 0x8000000000000000. As the -O0 version CORRECTLY reports, this does not round-trip back to the same value in the "long" type. Many other values, though not all, down to about 1/1024 of that value (1 / 2^(63-53)) will also fail to round-trip for similar reasons.

Unless my coffee-deficient brain is missing something at the moment, it should be the case that any integer with 53 bits or fewer between the first and last 1 bit (inclusive) will roundtrip cleanly. Any other integer will not.

Edit: fixed a typo above, and coded up the idea I expected to work and ran it through quickcheck for a few min, and this version seems to be correct ('int' return rather than bool is just because haskell's ffi doesn't natively support C99 bool):

    #include <limits.h>
    
    int fits(long x) {
      if (x == LONG_MIN) return 0;
    
      unsigned long ux = x < 0 ? -x : x;
      while (ux > 0x1fffffffffffffUL && !(ux & 1)) {
        ux /= 2;
      }
    
      return ux <= 0x1fffffffffffffUL;
    }
parent mokus 6 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton