| | タイトル | : Re^5: 計算の誤差について |  | 記事No | : 13748 |  | 投稿日 | : 2009/06/11(Thu) 11:30 |  | 投稿者 | : 魔界の仮面弁士 | 
 > 100.1 か 90.2 かはわかりませんが、2進で表現しきれないということでしょうか?
 2 進で誤差なく表せる数は、(2^X) の累積で表せる物です。
 15.75 = (1 * 2^3) + (1 * 2^2) + (1 * 2^1) + (1 * 2^0) + (1 * 2^-1) + (1 * 2^-2) → 1111.11 {2進}
 10.00 = (1 * 2^3) + (0 * 2^2) + (1 * 2^1) + (0 * 2^0) + (0 * 2^-1) + (0 * 2^-2) → 1010.00 {2進}
 9.00 = (1 * 2^3) + (0 * 2^2) + (0 * 2^1) + (1 * 2^0) + (0 * 2^-1) + (0 * 2^-2) → 1001.00 {2進}
 4.50 = (0 * 2^3) + (1 * 2^2) + (0 * 2^1) + (0 * 2^0) + (1 * 2^-1) + (0 * 2^-2) → 0100.10 {2進}
 1.25 = (0 * 2^3) + (0 * 2^2) + (0 * 2^1) + (1 * 2^0) + (0 * 2^-1) + (1 * 2^-2) → 0001.01 {2進}
 
 10 進で誤差なく表せる数は、(10^X) の累積で表せる物です。
 999.99 = (9 * 10^2) + (9 * 10^1) + (9 * 10^0) + (9 * 10^-1) + (9 * 10^-2)
 100.10 = (1 * 10^2) + (0 * 10^1) + (0 * 10^0) + (1 * 10^-1) + (0 * 10^-2)
 90.20 = (0 * 10^2) + (9 * 10^1) + (0 * 10^0) + (2 * 10^-1) + (0 * 10^-2)
 4.50 = (0 * 10^2) + (0 * 10^1) + (4 * 10^0) + (5 * 10^-1) + (0 * 10^-2)
 1.25 = (0 * 10^2) + (0 * 10^1) + (1 * 10^0) + (2 * 10^-1) + (5 * 10^-2)
 
 
 ちなみに、「10 ÷ 3 は割り切れない」というのは、10 進や 2 進の場合の話であって、
 3 進であれば割り切れる数として表す事が可能です。
 
 「10 ÷ 3」
 10 進数 → 3.3333333… [無限小数]
 3 進数 → 10.1 [ちょうど割り切れる] = (1 * 3^1) + (0 * 3^0) + (1 * 3^-1)
 2 進数 → 11.010101… [循環小数]
 
 「1 ÷ 3」
 10 進数 → 0.333333… [無限小数]
 3 進数 → 0.1 [ちょうど割り切れる] = (1 * 3^-1)
 2 進数 → 0.010101… [循環小数]
 
 「1 ÷ 10」
 10 進数 → 0.1 [ちょうど割り切れる]
 3 進数 → 0.00220022002… [循環小数]
 2 進数 → 0.0001100110011… [循環小数]
 
 「1 ÷ 2」
 10 進数 → 0.5 [ちょうど割り切れる] = (5 * 10^-1)
 3 進数 → 0.111111… [無限小数]
 2 進数 → 0.1 [ちょうど割り切れる] = (1 * 2^-1)
 --------------
 
 桁数が無限にあれば、循環小数になっても正しい数値を表せますが、
 コンピュータのメモリは有限です。各変数は数バイト程度の領域しかないため、
 途中の桁で打ち切られ、その差が『誤差』となります。
 
 100.1 も 90.2 も、10進では小数部は 1 桁で表せていますが、
 これらの数を 2進数にすると、いずれも循環小数になってしまうのです。
 
 そして倍精度浮動小数点型では、内部が2進で管理されています。
 誤差を含んだ値同士を演算すれば、結果も誤差を含むことになるという事です。
 
 
 
 > 通貨型ですか。
 > 型による精度の所為ということでしょうか?
 
 通貨型だと問題が出なかったのは、通貨型の内部表現が、8バイトの「整数」であるからです。
 
 たとえば、123.45 という小数があった場合、通貨型の内部では 10,000 倍した「1234500」に相当する
 整数値で保持されています。ヘルプの『通貨型 (Currency)』の項も参照しておいてください。
 
 今回の 100.1@ - 90.2@ という演算であれば、「1001000」-「902000」=「99000」として内部処理され、
 これが 9.9000 という結果として表されているのだとイメージしてみてください。
 
 なお通貨型の場合、この「10,000 倍」の内部仕様があるために、
 「小数部の桁数が 4 桁を超える値を正しく扱えない」という点を覚えておいてください。
 ---------
 
 また、今回の件とは関係ありませんが、割り算を行う際にも注意してください。VB6 において
 a / b
 という除算を行うと、a, b 双方が通貨型であったとしても、結果は Double となります。
 殆どの場合、「/ 演算子」は、倍精度浮動小数点数型(Double)となる仕様である事を覚えておいてください。
 
 なお、a, b の型によっては、倍精度浮動小数点数型(Double)型以外を返すパターンもあります。
 単精度浮動小数点数型(Single) になる場合と 10 進型を返す場合です。
 詳細はヘルプで、/ 演算子の項を見ておいてください。
 
 |