为什么从无符号long long转换为double会导致数据丢失?

时间:2015-02-21 22:14:59

标签: c++ c visual-c++ floating-point

当我通过微软的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;
}

编译器给了我:

  

警告C4244说明:转换为&#39; unsigned long long&#39;双重&#39;可能会丢失数据。在线

currentD = b[i] - a[i]

我知道以某种方式重写代码会更好,我用双倍来解释差异的可能负值,但我只是好奇,为什么在世界范围内从无符号长转换为如果unsigned long long的范围从0到18,446,744,073,709,551,615并且double是double,则double会导致数据丢失  +/- 1.7E +/- 308?

2 个答案:

答案 0 :(得分:15)

IEEE双精度浮点数具有53位尾数。这意味着(大多数)大于2 53 的整数不能完全存储在双精度中。

示例程序(这适用于GCC,对{MSVC使用%I64u):

#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;
}

输出:

9007199254740991 9007199254740991.000000
9007199254740993 9007199254740992.000000

答案 1 :(得分:2)

double支持更大范围的可能值,但不能代表该范围内的所有值。一些无法表示的值是整数值,longlong long可以表示。

尝试将值分配给它无法表示的浮点变量意味着结果是一些近似值 - 一个接近但不完全相等的值。这表示潜在的数据丢失(取决于分配的值)。