34

C# で 10 進数値を乗算すると、奇妙な動作に気付きました。次の乗算操作を検討してください。

1.1111111111111111111111111111m * 1m = 1.1111111111111111111111111111 // OK
1.1111111111111111111111111111m * 2m = 2.2222222222222222222222222222 // OK
1.1111111111111111111111111111m * 3m = 3.3333333333333333333333333333 // OK
1.1111111111111111111111111111m * 4m = 4.4444444444444444444444444444 // OK
1.1111111111111111111111111111m * 5m = 5.5555555555555555555555555555 // OK
1.1111111111111111111111111111m * 6m = 6.6666666666666666666666666666 // OK
1.1111111111111111111111111111m * 7m = 7.7777777777777777777777777777 // OK
1.1111111111111111111111111111m * 8m = 8.888888888888888888888888889  // Why not 8.8888888888888888888888888888 ?
1.1111111111111111111111111111m * 9m = 10.000000000000000000000000000 // Why not 9.9999999999999999999999999999 ?

私が理解できないのは、上記のケースの最後の 2 つです。そんなことがあるものか?

4

2 に答える 2

2

数学者は、有理数とスーパーセット実数を区別します。有理数の算術演算は明確に定義されており、正確です。実数の算術演算 (加算、減算、乗算、および除算の演算子を使用) は、無理数が無理数の形式 (シンボリック) のままであるか、一部の式で有理数に変換できる場合にのみ「正確」です。 . たとえば、2 の平方根には 10 進数 (またはその他の有理数ベース) 表現はありません。ただし、2 の平方根に 2 の平方根を掛けたものは有理数であり、明らかに 2 です。

コンピューターとその上で実行される言語は、一般に有理数のみを実装します。これは、int、long int、float、倍精度、実数 (FORTRAN)、または実数を示唆するその他の名前などの名前の背後に隠されています。しかし、範囲が無限である有理数のセットとは異なり、含まれる有理数は限られています。

些細な例 - コンピュータにはありません。1/2 * 1/2 = 1/4 有理数のクラスがあり、分子と分母のサイズが整数演算の制限を超えない場合、これは正常に機能します。そう (1,2) * (1,2) -> (1,4)

しかし、利用可能な有理数が 10 進数であり、10 進数の後の 1 桁に制限されている場合 (実用的ではありません)、有理数 (浮動小数点数/実数など) を近似するための実装を選択するときに行われた選択を表す場合、1/2 は完全になります。 0.5 に変換可能な場合、0.5 + 0.5 は 1.0 に等しくなりますが、0.5 * 0.5 は 0.2 または 0.3 のいずれかでなければなりません!

于 2013-08-06T23:48:06.220 に答える