Why conversion from unsigned long long to double can lead to data loss?

c, c++, floating-point, visual-c++

Solution

An IEEE double-precision floating point number has 53 bits of mantissa. This means that (most) integers greater than 253 can't be stored exactly in a double.

Example program (this is for GCC, use `%I64u` for MSVC):

#include <stdio.h>

int main() {
    unsigned long long ull;

    ull = (1ULL << 53) - 1;
    printf("%llu %f\n", ull, (double)ull);

    ull = (1ULL << 53) + 1;
    printf("%llu %f\n", ull, (double)ull);

    return 0;
}

Output:

9007199254740991 9007199254740991.000000
9007199254740993 9007199254740992.000000

Problem

When I compile this trivial piece of code via Microsoft's VC 2008: ``` double maxDistance(unsigned long long* a, unsigned long long* b, int n) { double maxD = 0, currentD = 0; for(int i = 0; i < n; ++i) { currentD = b[i] - a[i]; if(currentD > maxD) { maxD = currentD; } } return maxD; } ``` The compiler gives me: warning C4244 stating: conversion from 'unsigned long long' to 'double', possible loss of data. On the line ``` currentD = b[i] - a[i] ``` I know that it's better to rewrite the code somehow, I use double to account for possible negative values of the difference, but I'm just curious, why in the world conversion from unsigned long long to double can lead to data loss if unsigned long long's range is from 0 to 18,446,744,073,709,551,615 and double is +/- 1.7E +/- 308 ?

Original source