3

uintlongulongおよびdecimalを IEEE 754 倍精度浮動小数点値として表す必要があるデータ型変換を実行しています。変換を実行する前に、IEEE 754 データ型に値を含めることができないかどうかを検出できるようにしたいと考えています。

強引な解決策は、キャストの周りに try-catch をラップして、 をダブル検索することですOverflowException特定のCLR ドキュメントを読むと、一部の変換では例外なく値が暗黙的に変更されることがわかります。

このチェックを行う簡単な方法はありますか? 実装の容易さよりも完全性を求めています。IEEE 754仕様をよく読んで、マティッサと指数を注意深くチェックするつもりだと思います...

私は、整数を正確に表現することに最も関心があり、浮動小数点の精度の低下は二次的な懸念事項であることを付け加えておきます (ただし、検討する価値はあります)。

編集: Int32 は IEE-754 として完全に表現できます。また、Decimalデータ型も問題の大部分です。

重要な更新:この質問を参照している場合は、次の質問も読む必要があります: IEEE-754 Double (64-bit float) vs. Long (64-bit Integer) Revisited

一部の非常に大きな値もIEEE-754で正確に表現できるという回答の欠陥に注意してください。これは値が正しく往復することを意味するかもしれませんが、私の本来の目的 (JavaScript に往復するかどうか) ではそうではありません。

また、CLR の System.Double 型にもバグがあるようです。これは、これらの値の往復が正しく許可されていないためです。

4

3 に答える 3

9

簡単な解決策は次のようになります ( x が int の場合):

if ((int)(double)x != x) { 
  // won't convert
} else {
  // will convert
}

などなど。

(double)x は、x を int から double に変換します。(int) はそれを再度変換します。したがって、 (int)(double)x は int を double に変換してから元に戻します。基本的に、コードは double への変換が元に戻せることを確認しています (したがって、double が int の正確な値を格納できることを確認しています)。

于 2009-10-21T15:31:39.917 に答える
1

これは主に、使用している数値範囲によって異なります。( doubleの場合) 15 桁以内である限り、整数の安全側にいる必要があります。

基本的に、考慮する必要があるのは有効桁数です。したがって、数値が有効桁数の制限よりも小さい限り、正確なままになります。それが大きくなると、精度が失われます (それらが整数であっても)。

したがって、数値が < 2^53 である限り、通常は問題ありません。

于 2009-10-21T15:32:36.387 に答える
1

IEEE 754 Double には仮数用に 52 ビットがあり、integer/longとの間で変換しているため、テストが非常に簡単です。整数が 52 ビット未満しか消費しない場合は、IEEE 754 double に問題なく変換できるはずです。

私は、intが32ビットでlongが64ビットであると仮定します(Javaの場合は確かに知っていますが、C#ではなくチェックが面倒です)。したがって、確かに int は署名と署名解除の両方で問題なく double に収まります。

ulong の場合、52 番目のビットよりも上位のすべてのビットが ((aULong && 0xFFF0000000000000) == 0) のようなものである場合は単純です。

長い間、その兆候を考慮に入れる必要があります。Long は 2 の補数ですが、IEEE754 はそうではありません (負のビットがあるだけです)。そのため、long が負の場合は、最初に -1 で時間を計ります (正の場合は何もしません)。次に、 ulong のようにチェックします。

お役に立てれば。

于 2009-10-21T15:52:01.917 に答える