c++ - 为什么从 unsigned long long 转换为 double 会导致数据丢失?

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

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

编译器给我:

warning C4244 stating: conversion from 'unsigned long long' to 'double', possible loss of data. On the line

currentD = b[i] - a[i]

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

最佳答案

一个 IEEE double float 有 53 位尾数。这意味着(大多数)大于 253 的整数不能精确地存储在 double 中。

示例程序(这是用于 GCC,使用 %I64u 用于 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;
}

输出:

9007199254740991 9007199254740991.000000
9007199254740993 9007199254740992.000000

关于c++ - 为什么从 unsigned long long 转换为 double 会导致数据丢失?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28652014/

相关文章:

基于范围的 for 循环中的 C++11 重新声明

c++ - 在 distcc 中禁用某些警告

c++ - 如何存储数据/我们如何获取存储在 unordered_map c++​​11 中存储桶中的数据

c++ - 如果我不使用 'delete' 会怎样?

c++ - 尝试使用 std::functional 和 std::bind 在 C++ 中创建 C# 样式的事件访问修饰符

c++ - 调用drawow会导致堆损坏

c++ - 将文件从另一个 .vcproj 链接/包含到现有 .vcproj

c - C 中的交错数组

c 指针到指针如何迭代它

c++ - CString转字符串(VC6)