我想我的 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 并了解发生了什么吗?
答案 0 :(得分:2)
-0.207010582f
是十进制浮点文字。但是您的计算机不使用十进制浮点数,它使用二进制浮点数。因此,该文字的值将四舍五入到 float
精度。
同样,-0.207010582
被四舍五入到 double
精度。虽然更接近,但它仍然不等于 -0.207010582
十进制。
由于 double
比 float
具有更高的精度,因此从 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 浮点表示。