5

数学では、(実数の)足し算は交換可能かつ結合的です。すべての数値 x、y、z に対して

x + y = y + x (可換性)

x + (y + z) = (x + y) + z (結合性)

実数の乗算も交換可能で結合的です。しかし、これは .NET の int と float に当てはまりますか? 反例歓迎。

編集:背景は、最近アルゴリズムを並列化したところ、その結果が繰り返し間で一貫性がなくなったことです。これは、アトミック計算が非決定論的な順序で返される (およびマージされる) ためであると推測されます。その場合、矛盾は、よりスマートな (しかし遅い) マージ アルゴリズム (マージ前に結果を並べ替える) によって修正できます。.NET 算術演算についてどのような仮定を立てることができるか知りたいです。

4

4 に答える 4

1

チェックされていないコンテキスト (デフォルト) では、オーバーフローの存在は結合性と可換性とは無関係です。

たとえば、 を取り0x7fffffff + 0x80000000 + 0xffffffffます。0xfffffffeどのように括弧を付けても、結果は(別名 -2) です。しかし、2回オーバーフローするの(0x7fffffff + 0x80000000) + 0xffffffffに対し、オーバーフローしません0x7fffffff + (0x80000000 + 0xffffffff)。(符号なし演算では、両方とも 1 回オーバーフローします)

これは一般的にも言えます。a + (b + c) = (a + b) + c in integer in C# (if unchecked) および Java。C および C++ では、符号付きオーバーフローが定義されていないため、これは符号なし整数に対してのみ保証されます。

于 2013-10-14T13:14:35.007 に答える
0

並列化されたリダクションでは:

floats.AsParallel().Sum();

...毎回異なる結果が期待できます。これは、作業が毎回異なる方法で分割され、数値を追加するときに異なる丸め誤差が発生するためです。

この問題を最小限に抑えるには、リダクションが float ではなく double で行われるようにしてください。ビットごとに同一の結果が必要な場合は、TPL または PLINQ を使用せず、独自の並列計算をロールする必要があります。

C# では、fp の精度が C++ ほど厳密に保証されていないことに注意してください。この SO の質問に対する Eric の回答を読んでください 。

于 2013-10-14T11:55:37.963 に答える