ここにあなたの苦境への鍵です:10
の産物である2
と5
。基数10の10進数で、k * 1/2 n * 1/5 mの任意の数値を正確に表すことができます。ここk
でn
およびm
は整数です。
別の言い方をn
すると-1 / nの数値に基数の因子の一部ではない因子が含まれている場合、その数値はその2進数/ 10進数/何でも展開の固定桁数で正確に表すことができません番号-繰り返し部分があります。たとえば、1/15 = 0.0666666666 ....は3(15 = 3 * 5)が10の因数ではないためです。
したがって、基数2で正確に表現できるもの(k * 1/2 n)は、基数10で正確に表現できます。
それ以外にも、数字を表すために何桁/ビットを使用しているのかという問題があります。いくつかの基数で正確に表現できる数がありますが、それは数桁以上のビット/ビットを必要とします。
2進数では、10進数で0.1が便利な1/10という数値は、2進数の固定ビット数で表現できる数値として表現することはできません。代わりに、数値は0.00011001100110011 ... 2です(0011部分は永久に繰り返されます)。
数1を見てみましょう2 /1010 2ビットより密接に。
____
0.00011
+ ---------
1010 | 1.00000
0
-
1 0
0
----
1 00 --------- +
0 |
----- |
1 000 |
0 |
------ | 繰り返す
1 0000 | ブロック
1010 |
------ |
1100 |
1010 |
---- |
100 ---- +
これは、1/3の長い除算を行おうとしたときに得られるものとまったく同じタイプです。
1/10、因数分解されたときは1 /(2 1 * 5 1)。ベース10(または10の倍数)のために、この数は終了し、として知られている定期的な数。繰り返される10進数の拡張は、繰り返し10進数と呼ばれ、繰り返しなくても永久に続く数字は無理数です。
この背後にある数学は、フェルマーの小さな定理を掘り下げます...そして、フェルマーまたは定理と言い始めると、それはMath.SEの質問になります。
10進数では表現できないが、2進数では表現できる数値はありますか?
答えはノーです'。
したがって、この時点で、有理数のすべての固定長のバイナリ展開は、固定長の10進展開として表現できることを明確にする必要があります。
ことができますC#で小数点以下でより密接に見てに私たちをリード.NETで10進浮動小数点と著者を与え、私はそれがどのように動作するかというのthatsを受け入れるだろう。
decimal型には、他の浮動小数点数と同じコンポーネントがあります:仮数、指数、および符号。いつものように、符号は1ビットだけですが、仮数の96ビットと指数の5ビットがあります。ただし、すべての指数の組み合わせが有効なわけではありません。値0〜28のみが機能し、それらは事実上すべて負です。数値はです。これは、そのタイプの最大値と最小値が+/-(2 96 -1)であり、絶対値での非ゼロの最小値が10 -28であることを意味します。sign * mantissa / 10exponent
すぐに指摘しますが、この実装のために、double
型には表現できない数字がありますdecimal
-範囲外の数字です。 Double.Epsilon
さ4.94065645841247e-324
で表すことができないdecimal
ではなく、缶double
。
ただし、decimalが表現できる範囲内では、他のネイティブ型よりも精度が高く、エラーなく表現できます。
他にもいくつかの種類があります。C#には、任意の大きな整数を表すことができるBigIntegerがあります。JavaのBigDecimal(最大2 32桁の長さの数字を表すことができる-これはかなりの範囲です)に相当するものはありません。ただし、少し調べてみると、手巻きの実装を見つけることができます。
有理数を正確に表すことができる合理的なデータ型を持つ言語もあります(したがって、1/3は実際には1/3になります)。
特にC#とフロートまたは有理数の選択については、.NETのDecimalフローティングパイントからJon Skeetに従うことにします。
ほとんどのビジネスアプリケーションでは、おそらくfloatまたはdoubleではなく10進数を使用する必要があります。私の経験則では、通貨などの人工の値は通常、10進浮動小数点でより適切に表されます。たとえば、正確に1.25ドルの概念は完全に合理的です。長さや重みなど、自然界の値の場合、バイナリ浮動小数点型はより意味があります。理論的には「正確に1.25メートル」ありますが、実際には決して発生しません。正確な長さを測定することは絶対に不可能であり、原子レベルで存在することはほとんどありません。私たちは、特定の許容範囲が関係していることに慣れています。