System.Math やたとえば MathNet.Numerics が double に基づいているのはなぜですか?

StackOverflow https://stackoverflow.com/questions/1680907

  •  16-09-2019
  •  | 
  •  

質問

のすべてのメソッド システム.数学 かかります double パラメータとして使用し、パラメータを返します。定数にも型があります double. 。チェックアウトしました MathNet.Numerics, そこでも同様のようです。

どうしてこれなの?特に定数の場合。そうじゃない decimal より正確なはずですか?これは計算をするときに便利だと思いませんか?

役に立ちましたか?

解決

これは、速度と精度の古典的なトレードオフです。

ただし、たとえば PI の場合、必要となる最大桁数は 41 であることに注意してください。

必要なPIの最大数桁は41です。プロトンの直径よりも少ない誤差で宇宙の円周を計算するには、Pi†の41桁が必要です。遭遇する可能性が高い円測定の問題については、PIで41桁が十分な精度であると結論付けるのは安全だと思われます。したがって、2002年に計算されたPIの1兆以上の桁で、41番目を超えるすべての数字には実用的な価値がありません。

さらに、10 進数と倍精度浮動小数点数では、内部ストレージ構造が若干異なります。Decimal は基数 10 のデータを格納するように設計されており、double (および float) はバイナリ データを保持するように作られています。バイナリ マシン (既存のすべてのコンピュータと同様) では、double はその範囲内の数値を格納するときに無駄なビットが少なくなります。

次のことも考慮してください。

System.Double      8 bytes    Approximately ±5.0e-324 to ±1.7e308 with 15 or 16 significant figures
System.Decimal    12 bytes    Approximately ±1.0e-28 to ±7.9e28 with 28 or 29 significant figures

ご覧のとおり、10 進数の範囲は狭くなりますが、精度は高くなります。

他のヒント

いいえ、10 進数は double やその他の型と同様に「正確」ではありません。の概念 "正確」(コンピュータの数値表現について話すとき)何が間違っているのか。どの型も絶対に 100% 正確に表現できます いくつかの 数字。符号なしバイトは、0 から 255 までの整数を 100% 正確に表します。ただし、分数や負の数、範囲外の整数には適していません。

小数は、特定のセットを 100% 正確に表します。 10進数 価値観。double (値を次を使用して格納するため) バイナリ IEEE 指数表現) は、次のセットを正確に表現します。 バイナリ 数字。一般に、どちらも他方より正確というわけではなく、単に目的が異なるだけです。

一部の読者にとって私が十分に明確ではないようなので、もう少し詳しく説明すると...

小数として表現できるすべての数値を数直線上にマークすると、次のようになります。 それらの隣接するペアには追加のものが存在します 無限大 実数の ない 小数として表現できます。double として表現できる数値についても、まったく同じことが言えます。数直線上のすべての小数を青でマークし、整数を除いてすべての倍精度を赤でマークした場合、同じ値が両方の色でマークされる場所はほとんどなくなります。一般に、マークの 99.99999 % (私のパーセンテージについてうるさく言わないでください) では、青のセット (小数) は赤のセット (倍精度) とはまったく異なる数値のセットです。

これは、青色のセットの定義自体が、それが基数 10 の仮数/指数表現であり、double が基数 2 の仮数/指数表現であるためです。基数 2 の仮数および指数として表される任意の値、 (1.00110101001 x 2 ^ (-11101001101001) 仮数値を取得することを意味します (1.00110101001) に 2 の指数乗を掛けます (指数が負の場合、これは 2 の指数の絶対値乗で割ることと同じです)。これは、指数が負の場合 (または仮数の一部が小数 2 進数の場合)、数値を 10 進の仮数と指数として表すことができず、その逆も同様であることを意味します。

実数直線上にランダムにある任意の実数については、青の小数点のいずれか、または赤の倍精度浮動小数点数のいずれかに近くなります。

10 進数の方が正確ですが、範囲が狭くなります。通常、物理演算や数学の計算には Double を使用しますが、金融や金融の計算には Decimal を使用します。

詳細については、msdn の次の記事を参照してください。

ダブルhttp://msdn.microsoft.com/en-us/library/678hzkk9.aspx

10進数http://msdn.microsoft.com/en-us/library/364x0z75.aspx

ここでの「それは私が望むことをしない」という議論のほとんどは「しかし、その方が速い」というもののようです。そうですね、ANSI C+Gmp ライブラリもそうですが、誰もそれを主張していませんよね?

特に精度を制御したい場合は、時間をかけてユーザーが制御可能な方法で正確な精度を実装した他の言語があります。

http://www.doughellmann.com/PyMOTW/decmal/

精度が本当に重要である場合は、数学者が使用するような言語を使用する方がよいでしょう。Fortran が好きではない場合は、Python が最新の代替手段になります。

どの言語で作業している場合でも、次の黄金律を覚えておいてください。種類の混合は避けてください...したがって、演算子 b を試行する前に、a と b が同じになるように変換してください。

推測を危険にさらすとしたら、これらの関数は内部で小数を使用しない低レベルの数学機能 (おそらく C の) を活用しているため、小数を返すにはいずれにしても double から 10 進数へのキャストが必要になると思います。さらに、10 進数値タイプの目的は精度を確保することです。これらの関数はそうではなく、 できない 無限の精度 (無理数など) を持たずに、100% 正確な結果を返します。

何かを正確にする必要がある場合は、Decimal も float も double も十分ではありません。さらに、Decimal は非常に高価であり、あまりにも頻繁に使用されるため、定期的なジョークになっています。

分数で作業し、究極の精度が必要な場合は、分数を使用してください。これは古いルールと同じで、必要な場合にのみ変換します。丸めルールもアプリやドメインなどによって異なりますが、適切な奇妙な例が​​ 1 つか 2 つ見つかるはずです。しかし、繰り返しになりますが、分数と究極の精度が必要な場合、答えは分数以外のものを使用しないことです。任意精度の機能も必要になる場合があることを考慮してください。

一般に CLR に関する実際の問題は、一般的な方法で数値を処理するライブラリを実装するのが非常に奇妙で明らかに壊れていることです。その主な原因は、不適切な原始的な設計と、そのプラットフォームで最も一般的なコンパイラの欠点です。Java の大失敗とほぼ同じです。

double は、ほとんどのドメインをカバーする最良の妥協策であることが判明し、MS JIT が約 15 年前の CPU テクノロジをまだ利用できないという事実にもかかわらず、うまく機能します。

[MSDN スローダウン コンパイラのユーザーへのメッセージ]

ダブルは内蔵タイプです。FPU/SSE コア (以前は「数学コプロセッサ」として知られていました) によってサポートされているため、非常に高速です。特に掛け算や科学関数の場合にそうです。

Decimal は実際には複数の整数で構成される複雑な構造です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top