0

重複の可能性:
Visual Studio 2008 で .9 - .8999999999999995 = 0.0000000000000055511151231257827 と表示されるのはなぜですか?
1.82 のような単純な double が 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、 は 6 ではなく 5 に等しいということです。これはなぜですか?

4

3 に答える 3

7

0.0006 は double として正確に表すことはできません。ほとんどの場合、保存される実際の結果は 0.00059999999 のようなものです... この値に 10000 を掛けると、6 よりわずかに小さい数値になります。これを整数型にキャストすると、5 に切り捨てられます (切り捨てられます)。

これは奇妙な動作ではありません。これが浮動小数点演算のしくみです。値 6 を取得したい場合は、切り捨てるのではなく、最も近い整数に丸める必要があります。

関連している

于 2012-11-09T20:16:11.330 に答える
2

私の推測では、浮動小数点の精度に関係していると思います。.0006 は、コンピューターではおそらく .0005999999999 のようなものです。次に、これに 10,000 を掛けてから、小数を落とす long としてキャストし、5.999999 が 5 になるようにします。

于 2012-11-09T20:17:41.297 に答える
0

代わりにa を使用してみてくださいlong double。これは浮動小数点の精度エラーです。これを修正する簡単な方法は、より正確な浮動小数点型を使用することです。切り捨てエラーでない限り、キャストする前に丸める必要があります。

于 2012-11-09T20:18:15.483 に答える