[解決済み] C#で浮動小数点演算は整合性が取れているのか?可能なのか?
質問
いいえ、これは別のものではありません。 "なぜ (1/3.0)*3 != 1" なのか。 という質問をします。
最近、浮動小数点数についてよく読んでいるんだ。 同じ計算でも結果が異なる場合がある アーキテクチャや最適化の設定が異なる場合
これは、リプレイを保存するビデオゲームで問題となる、あるいは ピアツーピアネットワーク型 (サーバー・クライアント型ではなく) プログラムを実行するたびに、すべてのクライアントがまったく同じ結果を生成することに依存している場合、1 つの浮動小数点演算の小さな不一致が、マシンによってゲームの状態が大きく異なることにつながります (あるいは 同じマシンで )
これは、quot;follow"しているプロセッサの間でも起こります。 IEEE-754 これは主に、一部のプロセッサ(すなわち x86)が 倍拡張精度 . つまり、80ビットのレジスタを使ってすべての計算を行った後、64ビットまたは32ビットに切り捨てるため、64ビットまたは32ビットの計算を行うマシンと異なる丸め誤差が発生するのです。
この問題に対する解決策をいくつかネットで見ましたが、すべてC#ではなくC++のものでした。
-
倍精度拡張モードを無効にする(これにより、すべての
double
を使用して、IEEE-754 の 64 ビットを使用して計算します。_controlfp_s
(Windows)の場合。_FPU_SETCW
(Linux?)、またはfpsetprec
(BSD)です。 - 常に同じコンパイラを同じ最適化設定で実行し、すべてのユーザーが同じCPUアーキテクチャを持っていることを要求する(クロスプラットフォームプレイはしない)。 なぜなら、私の "コンパイラ" は実際には JIT であり、これは プログラムを実行するたびに異なる最適化が行われる可能性があります。 これは無理だと思います。
-
固定小数点演算を使用し
float
とdouble
を完全に削除します。decimal
はこの目的のために機能しますが、はるかに遅くなり、すべてのSystem.Math
ライブラリ関数がサポートしています。
では。 は、C#でも問題ないのでしょうか? Windowsだけをサポートするつもりなら(Monoではなく)どうすればいいのでしょうか?
もし、そうなら。 は、私のプログラムが通常の倍精度で実行されるように強制する方法はあるのでしょうか?
そうでない場合は 何か便利なライブラリはありますか? 浮動小数点演算の一貫性を保つことができますか?
どのように解決するのですか?
.netで通常の浮動小数点を決定論的にする方法を私は知りません。JITterは、異なるプラットフォーム(または.netの異なるバージョン)間で異なる動作をするコードを作成することが許可されています。そのため、通常の
float
を決定論的な.netのコードで使用することは不可能です。
私が考えた回避策
- C#でFixedPoint32を実装する。これはそれほど難しくないが(私は半分ほど実装を終えた)、値の範囲が非常に小さいので、使うのが煩わしい。オーバーフローしないように、また、精度が落ちないように、常に気をつけなければならない。最終的には、整数を直接使うより簡単ではないことがわかった。
- C#でFixedPoint64を実装する。これはかなり難しいと思った。128bitの中間整数があれば便利なこともある。しかし、.net にはそのような型はない。
- カスタム32ビット浮動小数点を実装する。BitScanReverse 組込み関数がないため、これを実装する際にいくつかの問題が発生します。しかし、現在のところ、これが最も有望な道だと思います。
- 数学演算にネイティブコードを使用する。すべての数学演算でデリゲート呼び出しのオーバーヘッドが発生します。
私は、32ビット浮動小数点演算のソフトウェア実装を始めたばかりです。私の2.66GHzのi3で毎秒約7000万回の足し算/掛け算が可能です。 https://github.com/CodesInChaos/SoftFloat . もちろん、まだ非常に未完成でバグも多いのですが。
関連
-
[解決済み] 保護レベルによりアクセス不能になりました。
-
[解決済み] DBNullから他の型にオブジェクトをキャストすることができない
-
[解決済み] UnityでOnCollisionEnterが呼ばれない
-
[解決済み] intをenumにキャストするにはどうすればよいですか?
-
[解決済み] C#で文字列のエンコーディングを手動で指定せずに、一貫性のあるバイト表現を得るには?
-
[解決済み] 除算を強制的に浮動小数点にするにはどうしたらいいですか?除算は0に切り捨てられ続けますか?
-
[解決済み] JavaScriptで浮動小数点数の精度を扱うには?
-
[解決済み】10進数の代わりにdoubleを使うべき時は?
-
[解決済み】androidのリソース/値に浮動小数点値を追加する。
-
[解決済み】JavaのFloatとdoubleのデータ型について
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】エラー。「戻り値を変更できません」 C#
-
[解決済み】GDI+、JPEG画像をMemoryStreamに変換する際にジェネリックエラーが発生しました。
-
[解決済み】ここで「要求URIに一致するHTTPリソースが見つかりませんでした」となるのはなぜですか?
-
[解決済み】Excel "外部テーブルが期待された形式ではありません。"
-
[解決済み】OnCollisionEnter2Dが実行されない?
-
[解決済み】WSACancelBlockingCallの例外について
-
[解決済み】エラー「必要なフォーマルパラメータに対応する引数が与えられていない」を解決する?
-
[解決済み] 関数を終了するには?
-
[解決済み】プロセスが実行されているかどうかを知るには?
-
[解決済み】10進数の代わりにdoubleを使うべき時は?