投稿日 | : 2005/05/24(Tue) 13:13 |
投稿者 | : 魔界の仮面弁士 |
Eメール | : |
URL | : |
タイトル | : Re^5: |
# 以下で書いているのは、「Intの結果が変わることがある」という問題についてではなく、
# 「浮動小数点型の誤差」についての話題です。m(_ _)m
> double型の有効な桁数は15桁です。
これは、10進数表現での15桁、という意味ですよね。
間違ってはいないと思いますが、15桁以内ならば誤差が出ないというわけではないので、
元質問者の方(まだ見てるのかな)に対しては、この表現だと誤解を生むかも……。
たとえば「0.6」という値でも誤差は発生しますよね。「0.5」なら誤差はでませんが。
通貨型は、内部的には64bit整数(1万倍した値として格納)であり、0.5 も 0.6 も格納誤差は出ません。
10進型は、内部的には10進数であり、10進数表現の 0.5 や 0.6 を、やはり誤差無く格納できます。
しかし倍精度浮動小数点型は、内部的には2進数で処理されます。10進数表現の 0.5 であれば、
2進数表現の 0.1 として誤差無く格納できますが、10進数表現の 0.6 になってくると、
2進数では 0.10011001100110011…… という循環小数になってしまい、52ビットの仮数部に
収める際に、近似値ゆえの丸め誤差が生じます。
Dim A As Double, B As Double, C As Double, D As Double
A = 6.0#
B = 10.0#
C = 0.6#
Debug.Print (A / B) - C '誤差を含み、「2.22261445359528E-17」になってしまった
Debug.Print CDbl(A / B) - C 'この場合は、CDbl()で変換補正がかかり、「0」になる模様
D = A / B
Debug.Print D - C 'これも変換補正がかかるのか、「0」になるらしい
# あれ……。変換補正という用語でよかったんでしたっけ?
> 通貨型/通貨型が何型の答えを返すかを調べようとしていました。(^^;
う〜ん。「何型で返すか」は、先の TypeName で明らかでは無いでしょうか。
内部的にどのように演算されているかは、確認できませんけれども。
# 拡張倍精度浮動小数点演算を利用して、演算時は80bitで処理されているかもしれませんし、
# あるいはStarfishさんの説のように、Decimalで処理されているのかも知れませんが、
# それを確認することは、私にはできません……(マシン語読めないし)
> 割り算の結果をVariant型に入れると、倍精度浮動小数点数型を含むバリアント型に
それはつまり、実は10進型で返されているのだけれども、VarType / TypeName で
検証した際にはVariantを経由するため、Double になってしまう……という事でしょうか。
そのような例外があるとは思いませんでしたが、もしも本当にそうなのだとしたら、
10進型で返されている事を検証するのは、面倒そうですね。