B-Teck!

お仕事からゲームまで幅広く

【VBA】Round関数で四捨五入ができなかった話

VBAのRound関数は銀行家丸め(銀行型丸め、銀行丸めともいうらしい)になっているらしい。
ので何も考えないで四捨五入しようと思ったらできなかった。

銀行家丸めとは

銀行型丸めとは、切り捨てるときに一番近い偶数に近づける方法。
単に四捨五入していくよりも誤差の累積が少ないことで、銀行家に多く採用されたことから来ているらしい。
具体的に言うと、

四捨五入 銀行家丸め
0.5 1 0
1.5 2 2
2.5 3 2
3.5 4 4
4.5 5 4

と言った形。

VBAで四捨五入をするには

Int([数値] + 0.5)
Int([数値] * 10 + 0.5) / 10
Int([数値] * 100 + 0.5) / 100

Int関数は引数以下でかつ最大の整数を返す。
そのため、0.5を足すことで値を繰り上げることができる。
ただし、Int関数は整数を返すのみなので、対象の桁数に対して乗算、除算をしてやらないといけなくなる。

めんどくさいので部品にした

Excelのワークシート関数に合わせて整数桁の丸めも入れたので割と使いやすい気がする

Option Explicit

'/**
' * ExRound
' * 四捨五入をする関数
' * @param i_val 元の値
' * @param i_num 丸め桁数(負数の場合は整数桁の丸め)
' * @return 処理後の値
' */
Public Function ExRound(ByVal i_val As Double, Optional ByVal i_num As Long = 0) As Double
        ExRound = Int(i_val * (10 ^ i_num) + 0.5) / 10 ^ i_num
End Function

'以下テストコード
Sub test()
    '引数なし
    Debug.Print ExRound(0.5) = 1
    Debug.Print ExRound(1.5) = 2
    Debug.Print ExRound(2.5) = 3
    Debug.Print ExRound(3.5) = 4
    Debug.Print ExRound(4.5) = 5
    '引数あり
    Debug.Print ExRound(0.5, 0) = 1
    Debug.Print ExRound(1.5, 0) = 2
    Debug.Print ExRound(2.5, 0) = 3
    Debug.Print ExRound(3.5, 0) = 4
    Debug.Print ExRound(4.5, 0) = 5
    
    '小数点第二位
    Debug.Print ExRound(1.24, 1) = 1.2
    Debug.Print ExRound(1.25, 1) = 1.3
    '小数点第三位
    Debug.Print ExRound(1.234, 2) = 1.23
    Debug.Print ExRound(1.235, 2) = 1.24
    
    '10の位
    Debug.Print ExRound(124, -1) = 120
    Debug.Print ExRound(125, -1) = 130
    '100の位
    Debug.Print ExRound(1234, -2) = 1200
    Debug.Print ExRound(3456, -2) = 3500
End Sub