简体   繁体   English

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

[英]A curious result about conversion between double and int in C++

My Problem: 我的问题:

Try to figure out the result of the following C++ snippet: 尝试找出以下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;
}

On Windows, I compiled and run the above code with VS2008 SP1 and get: 在Windows上,我使用VS2008 SP1编译并运行了上面的代码,并获得:

509
610

While on Linux, I compiled and run the same code with g++ and get: 在Linux上,我使用g ++编译并运行相同的代码,并得到:

509
609

What is the problem of the code? 代码有什么问题?

Sorry I have tried to figure a title for the problem thus I could have searched around. 对不起,我试图为这个问题找到一个标题,所以我可以四处搜寻。 However, I can't name this problem, so I directly present it here. 但是,我无法命名此问题,因此我在此直接提出。

Any advice is appreciated. 任何建议表示赞赏。

double is not an exact type, as you can see by applying the std::numeric_limits typetrait : 如您通过应用std::numeric_limits typetrait可以看到, double 不是确切的类型:

#include <limits>

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

Thus computations involving doubles are only approximate, and there is nothing wrong about what you observe. 因此,涉及双打的计算仅是近似的,您观察到的内容没有错。

There is no problem with your code. 您的代码没有问题。

In general, with double (and float) being binary, you can only ever make precise representations of fractions of powers of 2. Thus, if the decimal part is only made up of terms like 1/2, 1/4, 1/8, 1/16 etc. a float or double will be exact (unless you run into precision problems, of course). 通常,双精度(和浮点)为二进制,则只能精确表示2的幂的分数。因此,如果小数部分仅由1 / 2、1 / 4、1 / 8之类的项组成,1/16等。浮点数或双精度数将是精确的(当然,除非遇到精度问题)。

Now, "0.1" is 1/10, which is actually 1/2 * 1/5. 现在,“ 0.1”是1/10,实际上是1/2 * 1/5。 5 is not a power of two, thus "0.1" can't be represented in binary, it can only be approximated. 5不是2的幂,因此“ 0.1”不能用二进制表示,只能近似表示。

double to int conversion is done by truncation unless otherwise specified. 除非另有说明,否则doubleint转换是通过截断完成的。 In your case, due to loss of precisions while rounding the numbers (and a small amount of bad luck as noted by MSalters since this only happens near some "edge" values). 在您的情况下,由于四舍五入时精度的损失(以及MSalters指出的一小笔不幸,因为这仅发生在某些“边”值附近)。

Here are few possible reasons for the difference in behaviour between compilers/OS: 以下是导致编译器/操作系统之间行为不同的几种可能原因:

  • Optimizations: some compilers implement compile time floating operation with infinite precision. 优化:一些编译器以无限的精度实现编译时浮动操作。 Since your code is simple it is possible for the compiler to do the computation at compile time with infinite precision. 由于您的代码很简单,因此编译器可以在编译时以无限的精度进行计算。 (Have you checked the generated ASM code ?) (您是否检查了生成的ASM代码?)
  • Using different internal representation. 使用不同的内部表示形式。 Since you are running windows you are using an x86 or an x86-64 CPU that implements floating points with more than 64 bits see this for some details. 既然你运行的是Windows您使用的是86或超过64位浮点实现的点X86-64 CPU看到对一些细节。
  • Use of a different architecture entirely (are both your OS 64 bit ?) 完全使用其他体系结构(您的OS都是64位的吗?)

As one of the rules of The elements of programming styles by Kernighan and Plauger stated. 正如Kernighan和Plauger所说的“编程风格元素 ”的规则之一。

10.0 times 0.1 is hardly ever 1.0 10.0乘以0.1几乎不会是1.0

Meaning that floats don't behave like mathematical real numbers. 这意味着浮点数的行为不像数学实数。 There is a standard (IEEE 754) how you can implement floats but its not part of the C standard but only in C#. 有一个标准(IEEE 754),您可以如何实现浮点数,但它不是C标准的一部分,而仅在C#中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM