将双精度数转换为无符号整数

10

我遇到了将Double类型的值转换为int类型的问题。我尝试运行以下代码:

int main()
{
    double val_d= 6.25e-05;
    cout << (1/val_d) << endl;
    unsigned int val_ui = (unsigned int ) (1/val_d);
    cout << val_ui << endl;
}

将double转换为int可能会移除小数部分,但整数部分应该保留不变。

我得到的输出是: 16000 15999

那么为什么这里的输出不同呢? 这只在Fedora上发生。在Windows和Ubuntu上,它可以正常工作(两个输出都是16000)。

我调整了上面的代码并得到了以下结果:

int main()
{
  double val_d= 6.25e-05;
  cout << (1/val_d) << endl;
  double val_intermediate =  (1/val_d) ;
  cout << val_intermediate << endl;
  unsigned int val_ui = (unsigned int ) val_intermediate;
  cout << val_ui << endl;

}

新的输出是 16000 16000 16000


5
它输出了什么?你的预期输出是什么?这不就是你得到的吗:http://ideone.com/0eXhl - Nawaz
1
我实际上在这里没有看到问题。有什么出错了吗?你面临的问题是什么?你的代码是否没有按照你的期望工作? - Rook
1
我不太清楚你的实际问题是什么。它是否按照您的期望工作?它在做什么,您希望它做什么? - jcoder
它似乎如预期的那样运作:http://ideone.com/VkTov 对于两个输出都给出16000。 - Paul R
解决浮点数算术及其它类似问题的标准答案,请参考:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html - Paul R
显示剩余2条评论
3个回答

16

当将源文本“6.25e-05”解释为十进制数字并转换为双精度浮点数时,由于浮点数的精度有限,每个二进制位的值都是2的幂次方,而不是十进制数字,因此无法完全表示。最接近6.25e-5的IEEE 754双精度浮点数为6.25000000000000013010426069826053208089433610439300537109375e-05,或以十六进制浮点数表示为0x1.0624dd2f1a9fcp-14。

当取其倒数时,精确的数学结果再次无法完全表示,因此必须再次舍入。最接近的双精度浮点数为16000或0x1.f4p+13。

C++标准允许实现使用比名义类型要求更高的精度来计算浮点表达式。一些实现使用扩展精度,特别是英特尔的80位浮点类型,它具有64位的有效数字。(普通的双精度浮点数具有53位有效数字。)在这种扩展精度下,其倒数为0xf.9fffffffffffe89p+10或15999.99999999999966693309261245303787291049957275390625。

显然,当将扩展精度结果截断为整数时,结果为15999。

将长双精度浮点数舍入为双精度浮点数会产生16000。(可以使用显式转换为double来完成此操作;不需要将中间值分配给double对象。)


6

舍入方式的不同。

  1. (1/val_d) - double类型会被舍入为最接近双精度表示的数字;(例如:3.6999999999999999 == 3.7)
  2. (unsigned int ) (1/val_d) - 当强制转换为int类型时,小数部分会被截断,这将导致向下舍入;(例如:int(3.6) == 3)

1

将浮点值转换为整数值会删除小数部分,前提是结果可以用整数类型表示(即值不太大而无法容纳)。插入到流中四舍五入该值,这可能会产生不同的结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接