web-dev-qa-db-ja.com

浮動小数点演算を処理するときに参照透過性を想定できますか?

純粋な関数は、同じ入力が与えられた場合に同じ出力を生成すると想定されます。 (それ以外の場合)副作用のない関数が浮動小数点数で計算するとします。数値エラーにより、これらの出力は異なる場合があります(システム、並列処理、コンパイラの最適化に応じて...)たとえば https://stackoverflow.com/questions/2342396/why-does-this-floating-point -calculation-give-different-results-on-different-mac 。したがって、技術的には関数は参照透過的ではありません。

異なるが関連する問題は、浮動小数点数に加算モノイドを定義する場合です。 FPでの基本となる主要な仮定は、追加の結合性に関するものであり、有限精度の下では違反されます。 http://www.walkingrandomly.com/?p=538 基本的な例。

関数型プログラミングに対するそのような違反の実際的な関連性はありますか?そうでない場合、単純に参照の透明性を想定する必要がありますか?または、たとえば精度を犠牲にして数値結果の再現性が高い言語を選択するなどして、最大のRTを目指して努力する必要がありますか?

5
esc_space

関数型プログラミングに対するそのような違反の実際的な関連性はありますか?

私はあなたが答えが「はい」であるというかなり明確なケースを作ったと思います。

そうでない場合、単純に参照の透明性を想定する必要がありますか?

これが大丈夫であると私が見る唯一の方法は、あなたが気にかけている唯一のことは、結果がほぼ同じかどうかであるかどうかです。しかし、乗算と除算が関係する場合、小さな不整合がさらに大きくなる可能性があるため、これには大きな落とし穴があります。

または、たとえば精度を犠牲にして数値結果の再現性が高い言語を選択するなどして、最大のRTを目指して努力する必要がありますか?

精度を下げる必要はないと思います。これらの問題を解消するには、2進数の分数を使用して別の基数の数値で計算しようとすることを回避する型を使用します(および/または浮動小数点のすべての歴史的な奇妙さを持ちません)。無限小数精度の型は固定小数点精度の型と同じように機能します。浮動小数点型と同じスペースを使用する場合は、ある程度の精度を犠牲にする必要があります。

3
JimmyJames

それはすべて、実装の品質に依存します(必要な実装のプロパティを保持するために、実装が速度をあきらめる必要がある場合もあります)。

C、C++などでは、同じ実装のまったく同じステートメントが異なる結果をもたらす可能性があります。たとえば、ループでは、偶数のすべての反復で結果が1つの方法で計算され、奇数のすべての反復で別の方法で計算される場合があります。これが最も極端なケースです。それほど極端ではない:異なる場所で同じコードを使用すると、異なる結果が得られる場合があります。プログラムの2つの異なる実行で同じコードを使用すると、結果が異なる場合があります。 2つの異なる実装で同じコードを使用すると、結果が異なる場合があります。あなたの質問に関する限り、最も極端なケース(同じ結果でも異なる結果が出る)だけが問題になると思います。

これが発生するかどうかは、実装の制御下にある必要があります。しかし、あなたが与えた例(異なる結果を与える2つの実装)は問題ではありません(まあ、それは問題ですが、参照の透明性とはまったく無関係です)。実装は、同じプログラムの実行時に、同じデータを使用して同じコードを1回、複数回、遅延させても、常に同じ結果が得られることを保証する必要があります。同じ結果が得られるはずであるがそうではない2つの異なる関数があっても、その点では問題ではありません。

もちろん、言語は浮動小数点演算を自由に定義できるため、実装の自由度が低くなり、問題はなくなります。

2
gnasher729

参照透過性の違反は、その上に構築した場合の問題です。関数について推論することによってのみそれに基づいて構築することができ、その推論では実際にRTプロパティを使用します。テキストからの感想:おそらく、参照の透明性が侵害されている場所で浮動小数点計算の仕様不足] [たとえば、コンピュータ間通信]:関数型プログラミングを適用することすらありません。関数型プログラミングの利点を享受するために、ソフトウェアシステム全体を関数型に完全に表現する必要はありません。言い換えると、関数型プログラミングの適用は部分的であり、それでも非常に有益である可能性があります。関数型プログラミングは(全部かゼロか)ではなく(より優れた)パラダイムです。

浮動小数点演算による代数的プロパティの違反を心配します。代数的推論と関数型プログラミングはどちらもなしで実行できるため、この問題は関数型プログラミングとは強く関連していません。

しかし、心配はまだ有効です。これらの代数プロパティは、数値型の等式関数に基づいています。その等価テストがIEEE定義(ほとんどのプログラミング環境のデフォルト)である場合、浮動小数点数の合計は結合的ではないため、型はSemigroupインターフェースを実際に実装できません。しかし、その数値タイプを「近似」ラッパータイプにラップし、生の数値タイプの合計関数を近似レベルに引き上げ、近似の近似等価テスト関数を与えることができます[常にtrueを返します]。次に、近似は厳密な代数的意味でセミグループを実装できます。これは原則的なコーディング手法ですが、一部のソフトウェアエンジニアは、実際の面倒な作業を行わないことを選択し、生の浮動小数点数型のSemigroup実装はおおよその意味で解釈されることを覚えておいてください。

1
libeako