【VBA】「1.1 - 1.0 = 0.1」がFalseに!?浮動小数点数の罠とCurrency型の正しい使い方
VBAで小数の計算を行ったとき、「1.1 - 1.0 = 0.1 なのに False になる」という不思議な現象に出会ったことはありませんか?一見すると絶対に一致するはずのシンプルな引き算ですが、数値の末尾に @ をつけると True になります。
この記事では、イミディエイトウィンドウの実行結果をもとに、VBAにおける「浮動小数点数の誤差のなぞ」と、それを解決する「通貨型(Currency)」の秘密、そして実務における使い分けの基準を分かりやすく解説します。
1. イミディエイトウィンドウの実験結果
まずは、VBAのイミディエイトウィンドウで次のような引き算の評価式を実行した結果を見てみましょう。
False
? 1.1@ - 1.0@ = 0.1@
True
なぜ 1.1 - 1.0 の結果が 0.1 と一致しないのでしょうか?その理由は、コンピュータが小数を扱うときに使用する「浮動小数点数(Double型など)」の仕組みにあります。
コンピュータは内部で数値をすべて「2進数」で表現しています。「1.1」や「1.0」といった小数は、2進数に変換すると無限小数になってしまい、正確に表現できません。その結果、ごくわずかな丸め誤差(端数)が発生し、1.1 - 1.0 の計算結果は厳密には 0.09999999999999988 のような値になってしまいます。そのため、0.1 と比較したときに一致せず False になってしまいます。
2. 通貨型(Currency)の「@」が持つ秘密
では、2つ目の式にある 1.1@ - 1.0@ = 0.1@ が True になるのはなぜでしょうか?
ここで使われている @ は、VBAで「通貨型(Currency型)」の数値リテラルであることを明示する型文字です。通貨型には次のような強力な特徴があります。
- 固定小数点数での演算:浮動小数点数のような「2進数による丸め誤差」が発生しません。
- 小数点以下4桁までの精度:内部的には整数として扱われ(10,000倍した整数で計算)、小数点以下4桁までの正確な計算を保証します。
- 金額や端数計算に最適:消費税の計算や、わずかなズレも許されない厳密な引き算・足し算のために用意されています。
数値の末尾に @ をつけることで、VBAはこれをDouble型ではなくCurrency型として正確に計算するため、誤差が生じずピッタリ一致して True になります。
3. VBAコードでの実装例
実際のVBAコードで、通貨型と通常の浮動小数点数(Double型)の挙動の違いを確認してみましょう。
Dim a As Currency, b As Currency, c As Currency
Dim d As Double, e As Double, f As Double
' 通貨型(Currency型)を使った計算(正確)
a = 1.1@
b = 1.0@
c = 0.1@
If c = (a - b) Then
Debug.Print "Currency型: 一致しました(True)"
Else
Debug.Print "Currency型: 一致しません(False)"
End If
' 通常の浮動小数点数(Double型)を使った計算(誤差が出る)
d = 1.1
e = 1.0
f = 0.1
If f = (d - e) Then
Debug.Print "Double型: 一致しました(True)"
Else
Debug.Print "Double型: 誤差により一致しません(False)"
End If
End Sub
4. 通貨型(Currency)と 倍精度浮動小数点型(Double)の使い分け
万能に見える通貨型ですが、どのような場面でもCurrencyを使えばいいというわけではありません。以下の基準を目安に使い分けましょう。
【通貨型(Currency)を使うべきケース】
- お金や金額・税金の計算をするとき(1円たりともズレが許されない業務システムなど)
- 小数点以下の桁数が固定されており、厳密な一致判定(
=)を行いたいとき - ※扱える範囲は「整数部が最大15桁、小数部が4桁まで」となります。
【倍精度浮動小数点型(Double)を使うべきケース】
- 科学技術計算や統計・物理演算など、非常に大きな数値や小さな数値を扱うとき(例:
1.23e-10のような指数表現が必要な場合) - 小数点以下が5桁以上ある細かい数値を扱うとき(Currency型では小数点以下5桁目以降が四捨五入されて切り捨てられてしまうため)
- マクロ内で単純な四則演算や平均値・割合などを出すだけで、厳密なイコール判定をしないとき
5. まとめ
- 通常、VBAの数値リテラルは何も指定しないとDouble型になり、小数の計算などでわずかな丸め誤差が発生する。
- 金額計算や、厳密な小数の比較が必要な場面では、末尾に
@をつけるか、変数に Currency型 を明示する。 - 小数第5位より細かい値や科学的な計算を扱う場合は、従来通り Double型 を選ぶ。
「なぜか小数の計算結果が微妙にズレてしまう…」とお悩みのときは、データの性質に合わせて通貨型(Currency)や型文字 @ の活用を検討してみてください!