关于C ++中double和int之间转换的一个奇怪结果

时间:2012-09-10 14:18:51

标签: c++ c type-conversion

我的问题:

尝试找出以下C ++代码段的结果:

#include <iostream>

int main(int argc, char* argv[])
{
    double a = 5.1;
    int b = a * 100;
    std::cout << b << std::endl;

    double c = 6.1;
    int d = c * 100;
    std::cout << d << std::endl;
}

在Windows上,我使用VS2008 SP1编译并运行上面的代码并获取:

509
610

在Linux上,我使用g ++编译并运行相同的代码并获取:

509
609

代码有什么问题?

抱歉,我试图找出问题的标题,因此我可以搜索一下。但是,我不能说出这个问题,所以我直接在这里提出。

感谢任何建议。

4 个答案:

答案 0 :(得分:5)

double 是一种确切类型,您可以通过应用std::numeric_limits typetrait看到:

#include <limits>

static_assert(std::numeric_limits<double>::is_exact == false);

因此涉及双打的计算只是近似的,并且你所观察到的内容没有任何错误。

您的代码没有问题。

答案 1 :(得分:2)

一般情况下,double(和float)是二进制的,你只能对2的幂的分数进行精确表示。因此,如果小数部分只由1/2,1 / 4等词组成, 1 / 8,1 / 16等等,浮点数或双精度都是准确的(当然,除非你遇到精度问题)。

现在,“0.1”是1/10,实际上是1/2 * 1/5。 5不是2的幂,因此“0.1”不能用二进制表示,它只能近似。

答案 2 :(得分:1)

除非另有说明,否则

doubleint转换是通过截断完成的。在你的情况下,由于在舍入数字时精度损失(以及MSalters指出的少量坏运气,因为这只发生在一些“边缘”值附近)。

以下是编译器/操作系统之间行为差异的几个可能原因:

  • 优化:一些编译器以无限精度实现编译时浮动操作。由于代码很简单,编译器可以在编译时以无限精度进行计算。 (您检查了生成的ASM代码吗?)
  • 使用不同的内部表示。由于您正在运行Windows,因此您使用的是x86或x86-64 CPU,它实现了超过64位的浮点,请参阅this了解一些详细信息。
  • 完全使用不同的架构(你的OS是64位吗?)

答案 3 :(得分:1)

作为的规则之一,Kernighan和Plauger所描述的编程风格元素

  

10.00.1几乎不会1.0

意味着浮动不像数学实数那样。有一个标准(IEEE 754)如何实现浮点数,但它不是C标准的一部分,而只是在C#中。