2012-04-24 13 views
11

グラフにパスを見つけて累積ウェイトを出力するプログラムがあります。グラフのすべての辺は、小数点以下2桁までの浮動小数点形式で0〜100の個々のウェイトを持ちます。0 + 0 + 0 ... + 0!= 0

Windows/Visual Studio 2010では、0ウェイトのエッジからなる特定のパスに対して、正しい合計ウェイトを出力します。ただし、Linux/GCCでは、パスのウェイトは2.35503e-38です。私は浮動小数点によって引き起こされたクレイジーバグの経験は豊富ですが、0 + 0は0以外のものと等しくなるでしょうか?

これは私が考えることができるのは、プログラムがいくつかの重みを整数として扱い、暗黙の強制を使って合計に加算するということだけです。しかし、0 + 0.0fはまだ0.0fに等しい! クイックフィックスとして、私は0.00001より少なくても合計を0に減らし、これは私のニーズには十分です。しかし、どのようなvodooがこれを引き起こしますか?

注:詳述する: Iグラフの重みのいずれもが私はこの範囲を超えていないと、この特定の経路における重みの全てが全て0

EDITであることをことを100%確信私は、ファイルからウェイトを読み込み、それらをコードに手動で0.0fに設定することを試みました。これらのウェイトを合計に追加する以外の操作は実行されていません。

+19

最小のテストケースを構築できますか? –

+0

@OliCharlesworthそれは私がやろうとしてきたことです、これまでは運がありません。関連するコードの量はあまりに多いですが、私はより小さな範囲でバグを再現しようとし続けます。この背後には明らかな理由があることを期待していました。 –

+0

マシンイプシロンの定義を調べることをお勧めします。これはここであなたのエラーの原因となっているようです。 – andre

答えて

11

IEEE浮動小数点数であり、正確にゼロにはならないためです。

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

+3

しかし、問題は:なぜですか? (なぜ、それがゼロでないのか?)しかし、OPからテストケースを見る必要があるので、それは(まだ)答えることができません。 –

+0

私は、私の学部の数値解析コースで浮動小数点数をかなり研究しましたが、0 + 0は0以外の何かになるはずがありませんでした。 –

+0

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htmなぜ0は0ではないのですか?私は "0"が0であり、IEEE 754の規則で正確に表現されていることを "ゼロ"セクションが言ったと思います。 –

3

それは「は0.0f」の値を含むあなたのフロートが実際には0.0f(ビット表現0x00000000の)が、約0.0と評価され、非常に少ない数ではないこととすることができます。 IEEE754仕様で浮動小数点表現を定義する方法のために、たとえば仮数が非常に小さく、指数が0の場合、絶対値は0になりませんが、0に丸められます。ただし、回数は、ごくわずかな量が累積して最終的に非ゼロになる値になります。ここで

が非ゼロであること0の錯覚を与える場合を例です:

float f = 0.1f/1000000000; 
printf("%f, %08x\n", f, *(unsigned int *)&f); 
float f2 = f * 10000; 
printf("%f, %08x\n", f2, *(unsigned int *)&f2); 

を、あなたの変数にリテラルを割り当て、それらを追加する場合は、しかし、どちらかのコンパイラではない可能性があります0をメモリ内の0x0に変換します。そうであれば、これがまだ起きているのですが、CPUハードウェアには、検証作業の結果であるかもしれないALU操作を実行しているときに、0を0にすることに関するバグがある可能性もあります。

しかし、IEEE浮動小数点は近似値であり、特定の浮動小数点値の正確な表現ではないことに注意してください。したがって、浮動小数点演算には多少の誤差が生じることになります。

+0

いいえ、これは私の場合のようなものではありません。私は今まで分裂していません。私は変数に0と0.0fを代入して、それを追加します。 –

+0

私は錯覚を引き起こす可能性のある例を挙げています。もちろん、さまざまな状況によって同様のことが起こる可能性があります。 –

+0

そうですね、定数0を追加するとこれが発生する可能性はありません。 –

5

[...]小数点以下2桁までの浮動小数点数の形式です。

小数点以下2桁の浮動小数点数はです。浮動小数点数は、ほとんどの場合、2進浮動小数点数(小数2進数の仮数と整数指数)として表されます。小数点以下2桁の数字は、正確に表すことができません。例えば

0.20fは無実とラウンド分数として見えるかもしれませんが、

printf("%.40f\n", 0.20f); 

が印刷されます:0.2000000029802322387695312500000000000000を。

小数点以下2桁はありません.26個あります。

当然のことながら、ほとんどの実用的な用途では無視できる程度です。しかし、いくつかの計算を行うと、丸め誤差が増加し、特に0付近で表示されることがあります。

+0

私はゼロ以外の値についてこれを認識していましたが、問題が発生しているのは0だけです。しかし、ゼロの数が多少ずれている場合は、別の答えで指摘されているように問題を引き起こしている可能性があります。 –

+0

あなたは0と正確に対処していることをどのように知っていますか?それらはコンパイラの定数ですか?ファイルから読み込みますか? – rodrigo

+0

定数を使ってファイルから読み込もうとしました。 –

関連する問題