VBAの勉強を始めてみた

タイトルの通りVBAの勉強を始めました。仰々しくなく、シンプルな形で効率化を図ることを目指しています。VBA以外の話題もあるよ(笑)

Round関数の戻り値が違う?(ワークシート関数とVBA関数の違い)

Round関数が返す値はVBA関数とワークシート関数(俗に言うEXCEL関数)で違います。EXCELでのRound関数はご存知のとおり、引数で指定した桁数で四捨五入を行うものですが、VBAでは偶数丸め(ISO丸め、銀行丸めなどとも呼ばれる)という処理を行います。

具体的にはどういうことかというと、例えば「2.5」という数値を小数第1位以下で四捨五入すると「3」になります。これが、EXCELでのRound関数です。
しかしVBAで同じ処理をRound関数を使って行うと「2.5」は「2」になります。「1.5」は「2」になります。これは端数がちょうど0.5の場合に、繰り上げて偶数となる場合は繰り上げ、繰り上げて奇数となる場合は繰り上げしない(切り捨て)といった処理をしているからです。
0.1~0.4は切り捨て、0.6~0.9は切り上げることに関してはEXCEL関数と変わりません。イメージを掴みやすいように、下の表をご覧下さい。

 

Round関数の戻り値の違い

元の値 EXCEL VBA
0.1 0 0
0.2 0 0
0.3 0 0
0.4 0 0
0.5 1 0
0.6 1 1
0.7 1 1
0.8 1 1
0.9 1 1
1 1 1
1.1 1 1
1.2 1 1
1.3 1 1
1.4 1 1
1.5 2 2
1.6 2 2
1.7 2 2
1.8 2 2
1.9 2 2
2 2 2
2.1 2 2
2.2 2 2
2.3 2 2
2.4 2 2
2.5 3 2
2.6 3 3
2.7 3 3
2.8 3 3
2.9 3 3


ではなぜ、EXCELVBAでRound関数の仕様が違うのか?・・・は、実は分かりません(知りません)。が、偶数丸めにすると何か違いがあるのでしょうか・・・少し紐解いてみたいと思います。

まず、通常の四捨五入では端数0.5の繰り上がりによって、繰り上がり側に偏りが発生します。なので、データが多いほど繰り上がりによるプラス誤差が増えていきます。

偶数丸めは「銀行丸め」とも言われるくらいですから、誤差を小さく抑えることを目的としています。・・・どういうことかというと奇数と偶数で0.5の繰り上がりを相殺しているので、データが多くなっても誤差を小さく抑えることができるのです。

 

試しに、1.0~9.9の乱数を5,000個用意して、それぞれEXCELVBAのRound関数で処理したものを合計して、その誤差を見てみます。

f:id:kouten0430:20171007171955j:plain

 

次に乱数を10,000個まで増やして同じことをやってみます。四捨五入に関しては着実に誤差が増えていくのに対し、偶数丸めのほうは誤差が小さくおさまっています。

f:id:kouten0430:20171007172031j:plain

 

注意したいのは、Round関数で違いが生じるのは端数がちょうど「5」になる場合だけです。例えば「2.50000000000001」のような数値を小数第1位以下で四捨五入または偶数丸めを行っても結果は「3」になります。

1.00000000000000~9.99999999999999の乱数を5,000個用意して、小数第1位以下をRound関数で処理した結果の違いを見てみます。

f:id:kouten0430:20171007172149j:plain

合計はEXCELVBAで同じになります。なぜなら、5,000個程度の乱数では「2.50000000000000」のような偶数丸めの対象になるデータが皆無だからです。

 

でわまた('ω')ノ