首页 > 解决方案 > 将浮点数转换为双倍时精度损失

问题描述

我想我的 c++ 程序遇到了精度问题。而且我不明白为什么我的价值观会得到不同的结果。

res等于1321.0000001192093如果我写:

float sy = -0.207010582f;
double res = -1512.*((double)sy - (2. / 3.));

但 res2 等于1320.9999999839999如果我写:

double res2 = -1512.*(-0.207010582 - (2. / 3.));

当我写这个时,为什么甚至 syd 与 syd2 不同:

double syd  = -0.207010582f;
double syd2 = -0.207010582000000000;

有人可以帮我一把,将我的浮动正确地转换成双倍并了解发生了什么吗?

标签: c++castingfloating-pointdoubleprecision

解决方案


单精度

正如其他人所说,float sy = -0.207010582f;从单精度浮点文字初始化单精度(32 位)浮点变量。

这将被视为(在存储和计算中)该格式中最接近的可表示数字。这个数字是-0.20701058208942413330078125

你的代码是有效的float sy = -0.20701058208942413330078125;

您可以通过查看相邻的单精度浮点数来确认这是最接近的可表示值。

-0.20701059699058532714843750   // std::nextafter( sy, std::numeric_limits<float>::lowest() )
-0.20701058208942413330078125   // sy
-0.20701056718826293945312500   // std::nextafter( sy, std::numeric_limits<float>::max() )

双精度

双精度浮点数的情况完全相同,只是它们的分辨率提高意味着差异很小。egdouble dy = -0.207010582;实际上代表值0.20701058199999999853702092877938412129878997802734375

同样,可以表示的相邻值是——

-0.2070105820000000262925965444082976318895816802978515625  // std::nextafter( dy, std::numeric_limits<double>::lowest() )
-0.2070105819999999985370209287793841212987899780273437500  // dy
-0.2070105819999999707814453131504706107079982757568359375  // std::nextafter( dy, std::numeric_limits<double>::max() )

单到双转换

所有单精度浮点值都可以用双精度精确表示。因此,从单精度到双精度的转换不会丢失任何内容。


以上所有假设 IEEE754 浮点表示。


推荐阅读