1

私の問題:

次の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

4 に答える 4

5

doubletypetraitを適用するとわかるように、は正確なタイプではありませんstd::numeric_limits

#include <limits>

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

したがって、doubleを含む計算は概算であり、観察した内容に問題はありません。

コードに問題はありません。

于 2012-09-10T14:24:30.430 に答える
2

一般に、double(およびfloat)がバイナリである場合、2の累乗の小数部のみを正確に表現できます。したがって、小数部が1 / 2、1 / 4、1/8などの項のみで構成されている場合、1/16など。floatまたはdoubleは正確です(もちろん、精度の問題が発生しない限り)。

ここで、「0.1」は1/10であり、実際には1/2*1/5です。5は2の累乗ではないため、「0.1」は2進数で表すことはできず、概算することしかできません。

于 2012-09-10T14:29:34.910 に答える
1

KernighanとPlaugerによるプログラミングスタイルの要素のルールの1つとして述べられています。

10.0時代0.1はほとんどありません1.0

フロートが数学的な実数のように動作しないことを意味します。floatを実装する方法には標準(IEEE 754)がありますが、C標準の一部ではなく、C#でのみ実装できます。

于 2012-09-10T15:25:50.917 に答える
1

doubleint特に指定がない限り、変換は切り捨てによって行われます。あなたの場合、数値の四捨五入中に精度が低下するため(MSaltersが指摘するように、これは一部の「エッジ」値の近くでのみ発生するため、運が少し悪い)。

コンパイラとOSの動作が異なる理由として考えられるものは次のとおりです。

  • 最適化:一部のコンパイラは、コンパイル時の浮動小数点演算を無限の精度で実装します。コードは単純なので、コンパイラーはコンパイル時に無限の精度で計算を行うことができます。(生成されたASMコードを確認しましたか?)
  • 異なる内部表現を使用します。Windowsを実行しているため、64ビットを超えるフローティングポイントを実装するx86またはx86-64 CPUを使用しています。詳細については、これを参照してください。
  • 完全に異なるアーキテクチャの使用(両方ともOS 64ビットですか?)
于 2012-09-10T14:55:29.483 に答える