将 float 转换为 double 时精度损失

时间:2021-03-30 09:38:45

标签: c++ casting floating-point double precision

我想我的 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;

有人可以帮我一下,正确地将我的 float 转换为 double 并了解发生了什么吗?

2 个答案:

答案 0 :(得分:2)

-0.207010582f 是十进制浮点文字。但是您的计算机不使用十进制浮点数,它使用二进制浮点数。因此,该文字的值将四舍五入到 float 精度。

同样,-0.207010582 被四舍五入到 double 精度。虽然更接近,但它仍然不等于 -0.207010582 十进制。

由于 doublefloat 具有更高的精度,因此从 float 转换为 double不会失去精度。任何四舍五入都会更早发生。

答案 1 :(得分:2)

单精度

正如其他人所说,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() )

双精度

双精度浮点数的情况完全相同,只是它们的分辨率提高意味着差异很小。 例如 double 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 浮点表示。

相关问题