3

同じC++コードが異なるシステムで異なる結果をもたらす興味深いケースを見つけました。

#include <cstdio>
int main()
{
    int a=20, b=14;
    if(a*1.0/b*(a+1)/(b+1)==2) printf("YES!");
    else printf("NO!");
}

GCC4.6.3を使用してUbuntuLinux12.04でコンパイルすると、YESが出力されます。

GCC4.6.2を使用してWindows7でコンパイルすると、NOが出力されます。

ただし、以下を使用します。

double  c = a*1.0/b*(a+1)/(b+1);
if (c==2) printf("YES!");
...

YESを返します!両方のマシンで。

この違いが現れる理由はありますか?これはコンパイラのバージョンの不一致が原因ですか(パスレベルのバージョン番号はそれほど重要ではありません)?そして、なぜそれは実際にNOを出力するのですか?Windowsマシンでは、この条件は明らかに正しいですか?

4

5 に答える 5

14

浮動小数点型で等式比較を行っているため、一般に、マシン間(またはコンパイラー間など)の特定のビット精度の動作に依存するべきではありません。

考えられる理由には、浮動小数点の結果をワイド(80ビット)浮動小数点レジスタからいつ移動するかをコンパイラが選択することが含まれます(言語標準もIEEE-754浮動小数点標準も特定の要件を課していません(AFAIK))。

于 2012-05-09T15:40:49.830 に答える
12

これは単なる推測です。確実に知るには、コンパイラからのアセンブリ出力を確認する必要があります。

一方のコンパイラが中間結果を浮動小数点レジスタに残し、もう一方のコンパイラが結果をメモリに書き込んで、80ビットから64に丸める可能性があります。一方がSSEを使用し、もう一方が使用しない可能性もあります。

于 2012-05-09T15:47:25.260 に答える
2

これは浮動小数点演算のためです。代わりにイプシロン比較を使用してみてください。

#define EPSILON_EQUAL(a,b) ( fabs((a)-(b)) < (0.0001f) )

float f = a*1.0/b*(a+1)/(b+1);
if(EPSILON_EQUAL(f,2.0f)) printf("YES!");
于 2012-05-09T15:43:52.400 に答える
0

精度の問題により、このような浮動小数点数を比較するのは正しくないためです。

数学では2/3=(0.6666666 .....無限大まで)//小学校の数学:)質問はありません。

計算では、この計算は浮動小数点ユニットで実行されます(CPUと同様ですが、浮動小数点計算専用です)。これで、この浮動小数点ユニット(FPU)は、実際の答えに非常に近い数値を与える可能性がありますが、完全に同じではありません。結果が切り捨てられるためです。浮動小数点演算専用のフィールド全体があります。つまり、矛盾する結果が生じる可能性があるため、比較に浮動小数点数を使用しないでください。

于 2012-05-09T15:44:10.737 に答える
0

浮動小数点数間の同等性のテストには問題があります。これは丸め誤差が原因であり、インターネット上にはこれに関する多くのテキストがあります。

あなたはこれをここで、ここで、ここで、ここで、ここで、そして基本的にグーグル検索での結果を見ることができますfloating point equality

于 2012-05-09T15:47:07.117 に答える