使用双精度程序的意外行为

时间:2012-11-09 20:13:40

标签: c++ double

  

可能重复:
  Why does Visual Studio 2008 tell me .9 - .8999999999999995 = 0.00000000000000055511151231257827?
  Why do simple doubles like 1.82 end up being 1.819999999645634565360?

当我编译并运行以下程序时,我得到了一个非常奇怪的行为:

#include <iostream>

#define DIV 10000ll

long long gcd(long long a, long long b) {
  if(b==0) return a;
  else return gcd(b, a % b);
}

int main() {
  int t;
  std::cin >> t;
  while(t--) {
    double n1;
    std::cin >> n1;
    long long inum=(long long)(n1*DIV);
    std::cout << inum << std::endl;
    if(inum==0) { std::cout << 1 << std::endl; }
    else std::cout << DIV/gcd(inum,DIV) << std::endl;
  }
  return 0;
}

当我输入输入时:

1
0.0006

我得到输出

5
2000

这意味着:(long long)0.0006*10000等于5而不是6.为什么会发生这种情况?

3 个答案:

答案 0 :(得分:7)

0.0006不能完全表示为double。最有可能存储的实际结果类似于0.00059999999 ......当此值乘以10000时,它会给出一个略小于6的数字。将其转换为整数类型会将其截断(向下舍入)为5。

这不是奇怪的行为。这就是浮点运算的工作原理。如果你想得到值6,你应该舍入到最接近的整数而不是截断。

相关

答案 1 :(得分:2)

我的猜测是它与浮点精度有关。 .0006在计算机中可能类似于.0005999999999,然后将其乘以10,000,然后将其转换为长整数,使得小数点降,因此5.999999变为5。

答案 2 :(得分:0)

尝试使用long double代替它,它的浮点精度错误和修复它的简单方法是使用更精确的浮动类型。除非它是截断错误,在这种情况下你需要在之前围绕进行舍入。