Home » いちばんやさしいExcel VBAの教本 » VBAで小数の計算が合わない?

浮動小数点数を使った計算について、拙著『いちばんやさしいExcel VBAの教本』のP.125のワンポイントで以下のように書きました。

小数の計算を行うと間違いが生じるのがパソコンの原則ですから、誤差を一切生じさせたくない場合には、いったん整数に変換する処理を入れることも検討しましょう。

入門書であるため詳細な解説は省略しましたが、現在のコンピューターでは、意外と簡単な小数の計算で間違った値になります。

浮動小数点数の計算で間違える例

日々の生活の中で見かける、税込み金額から税抜き金額を計算するような場合でも、小数の計算を間違える様子を確認できます。

例えば、消費税率10%の商品で、税込み金額が110円のときに、消費税抜きの金額は100円であることは暗算でも計算できますが、浮動小数点数を使ってコンピューターに計算させると間違った値になってしまいます。

Sub sample_1()
 Debug.Print Int(110 / 1.1)
End Sub

上記のSubプロシージャを実行すると、イミディエイトウィンドウには「100」ではなく「99」が出力されます。

これはVBAだからというわけではありません。

例えばPython 3.8.0で、
  print(int(110/1.1))
というコードを実行しても、やはり「99」が出力されます。

コンピューターでは110÷1.1が100ではないことの確認

まず「110 / 1.1」の結果が「100」でないことを確認しましょう。

以下のSubプロシージャを実行します。

Sub sample_2()
 Debug.Print (110 / 1.1) = 100
End Sub

「110/1.1」の結果と「100」が等しいかどうかを調べた結果を出力しているSubプロシージャで、実行すると、
  False
が出力されます。

この結果から「110 / 1.1」は「100」ではないことがわかります。

110 / 1.1が99.9999...であることの確認

「110 / 1.1」の結果が、いくつなのかを推測しましょう。

以下のように編集して実行します。

Sub sample_2()
 Debug.Print (110 / 1.1) = 100
 Debug.Print (110 / 1.1) < 100
End Sub

今度は、
  False
  True
と出力されます。

「100/1.1」は「100」ではなく「100」より小さいということがわかります。

更に以下のように編集して実行しましょう。

Sub sample_2()
 Debug.Print (110 / 1.1) = 100
 Debug.Print (110 / 1.1) < 100
 Debug.Print (110 / 1.1) > 99.9999
End Sub

今度は、
  False
  True
  True
と出力されます。

つまり「110/1.1」は「100」よりも小さく「99.9999」よりは大きいということです。

「100」よりも小さく「99.9999」より大きい数値を、Int関数の引数にsample_1 Subプロシージャの中では指定したので、「99.9999...」の小数部分を削った「99」が出力されたのです。

ちなみに「110/1.1」は、Pythonで「format(110/1.1, '.20f')」を実行すると「99.99999999999998578915」くらいの値であることを確認できます。

整数にして計算するサンプル

※間違った記述をしていたため以降の内容を修正しました。ご指摘ありがとうございます! 2021-06-09

上記のような計算を正しく行う方法はいくつかあり、プログラミングに慣れた方なら誤差を生じないデータ型への型変換を行うのが一般的だと思いますが、整数にしてから計算する方法をまずは見ておきましょう。

Sub sample_3()
 Debug.Print (110 * 10) / 11
End Sub

このSubプロシージャなら期待どおり「100」が出力されます。
割る数を「11」と10倍して整数にするのにあわせて、割られる数も10倍しています。

コンピューターは、整数値ならば正しく計算できます。

通貨型に型変換して計算するサンプル

この例の課題は、人間が整数にする処理を行っている点です。

この整数にする処理を、コンピューターに任せることが可能です。それが「誤差を生じないデータ型への型変換を行う」です。

最初に試した、間違った結果になるSubプロシージャを以下のように修正してから実行してください。

Sub sample_1()
 Debug.Print Int(110 / 1.1)
 Debug.Print Int(110 / CCur("1.1"))
End Sub

間違った結果の「99」と正しい結果の「100」が出力されます。

ここで使っているCCur関数が、データ型を小数点以下4桁までなら間違えないCurrency型・通貨型に変換する、VBAの型変換関数の1つです。

VBAの通貨型は内部的には、小数を整数にして処理を行っています。
小数点以下が4桁以下であれば、誤差が発生しないため、実務では利用しやすいはずです。

小数点以下の桁数が4桁よりもっと必要な場合は、CDec関数・Decimal型の利用も検討しましょう。

最終更新日時:2024-01-04 13:28

[スポンサードリンク]

Home » いちばんやさしいExcel VBAの教本 » VBAで小数の計算が合わない?

「いちばんやさしいExcel VBAの教本」の記事一覧

検索


Copyright © インストラクターのネタ帳 All Rights Reserved.

.