当我通过微软的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?
答案 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
支持更大范围的可能值,但不能代表该范围内的所有值。一些无法表示的值是整数值,long
或long long
可以表示。
尝试将值分配给它无法表示的浮点变量意味着结果是一些近似值 - 一个接近但不完全相等的值。这表示潜在的数据丢失(取决于分配的值)。