【问题标题】:Unexpected behaviour of a program using doubles [duplicate]使用双打的程序的意外行为[重复]
【发布时间】:2012-11-09 20:13:40
【问题描述】:

可能重复:
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。为什么会这样?

【问题讨论】:

    标签: c++ double


    【解决方案1】:

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

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

    相关

    【讨论】:

    • 哇,我们差点一个字一个字地输入!
    • 你知道我该如何纠正吗?
    【解决方案2】:

    我的猜测是它与浮点精度有关。 .0006 可能类似于计算机中的 .0005999999999,然后将其乘以 10,000,然后将其转换为 long,这样 5.999999 就会变成 5。

    【讨论】:

      【解决方案3】:

      尝试改用long double,它是一个浮点精度错误,修复它的简单方法是使用更精确的浮点类型。除非它是截断错误,在这种情况下,您需要在 之前进行四舍五入。

      【讨论】:

      • 去掉第一句话,这个答案是对的。提高精度只会产生更长的位序列,但仍然不正确。
      猜你喜欢
      • 2016-03-18
      • 2018-08-07
      • 2013-01-27
      • 1970-01-01
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      • 2013-07-19
      • 1970-01-01
      相关资源
      最近更新 更多