🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の Round — 偶数への丸め(銀行丸め)と、ワークシートと違う理由

|

Excel VBA の Round — 偶数への丸め(銀行丸め)と、ワークシートと違う理由

TL;DR — VBA の Round は、セルで使う ROUND とは 別物 です。中間の値をいちばん近い 偶数 の桁へ丸めます(銀行丸め)。ですから Round(2.5)2Round(3.5)4 で、中間が常に切り上が るとは限りません。ワークシートの ROUND は中間を 0 から離れる向き に丸めます(2.53)。マク ロの合計をシートと一致させなければならないときは、ネイティブの Round ではなく Application.WorksheetFunction.Round を呼びましょう。

Sub RoundingIsNotWhatYouThink()
    Debug.Print Round(2.5)                              ' 2  - 3 ではなく偶数への丸め
    Debug.Print Round(3.5)                              ' 4  - 偶数への丸め
    Debug.Print Round(2.5, 0)                           ' 2  - 桁数を渡しても同じ規則
    Debug.Print Application.WorksheetFunction.Round(2.5, 0)  ' 3  - =ROUND(2.5,0) と一致
End Sub

RoundModRnd は、ワークシートの親戚のような関数に見え て、実は静かに違う挙動をする三つの計算ツールです。VBA は表計算ソフトではなく、汎用のプログラミング言語 だからです。なかでも Round はお金に直結します。規則を取り違えると、マクロの合計が、ほかのみんなが見てい るセルから 1 セントずれてしまうのです。

この記事で学べること

  • 考え方の軸 — VBA の計算はワークシートの計算では ない、そして Round がそれを証明する
  • 銀行丸めとは何か、そしてなぜ Round(2.5)2 なのにセルでは 3 になるのか
  • 第一の罠 — マクロの合計が、シート上の =ROUND() と 1 セント食い違う
  • Application.WorksheetFunction.Round でワークシートにぴたりと合わせる方法
  • なぜ IntFix は丸めではなく 切り捨て を行い、負の数で食い違うのか

考え方の軸:VBA の計算はワークシートの計算ではない

セルでの =ROUND(2.5, 0) の振る舞いは、あなたもよくご存じでしょう — 答えは 3 です。ですから、マクロ が初めて 2 を表示すると、バグのように見えます。ですが、これはバグではありません。VBA の Round 関数 は、銀行丸め(正式には 最近接偶数への丸め)と呼ばれる、別の、意図された規則に従います。数値がちょ うど中間の位置にあるとき、常に切り上げるのではなく、いちばん近い 偶数 の桁へ丸めるのです。

Debug.Print Round(0.5)    ' 0   (0 は偶数)
Debug.Print Round(1.5)    ' 2   (2 は偶数)
Debug.Print Round(2.5)    ' 2   (2 は偶数)
Debug.Print Round(3.5)    ' 4   (4 は偶数)

中間の値が、下・上・下・上と交互になっているのに注目してください。それこそがこの規則の狙いです。たくさ んの値にわたって、中間を常に切り上げると小さな 上向きの偏り が生まれますが、偶数へ丸めるとそれが打ち 消されます。統計的により公平な選択なのです — だからこそ、汎用の計算のために設計された言語はこれを採用 し、日常の計算のために作られた表計算ソフトは採用しなかったわけです。

この一文さえ押さえれば、この記事の残りはすべてそこから導かれます — 関数の名前は同じでも、規則は同じ ではない。 以下で述べることはすべて、Round が偶数へ丸めることの帰結です。

第一の罠:合計が 1 セントずれる

人々を検索へ走らせる失敗がこれです。あるマクロが請求明細を合計し、各行を小数点以下 2 桁に丸めます。する と総合計が、経理チームがシート上で維持している =ROUND(...) の列より 1 セント少なく出て、二つの数字が 合わなくなるのです。

' 半セントごとに偶数へ丸める - シートの =ROUND() から少しずつずれていく
lineTotal = lineTotal + Round(price * qty, 2)

個々の Round のずれはせいぜい半セントですが、何百もの半セントの値にわたると、偶数丸めとシートの「0 か ら離れる向き」の丸めが逆方向に引っぱり合い、その端数が積み重なります。エラーは何も出ません。ただ数字が 合わないだけです。出力が セルと一致しなければならない ときは、VBA の Round を使ってはいけません。

' シート上の =ROUND() とまったく同じ - 端数は 0 から離れる向きに丸める
lineTotal = lineTotal + Application.WorksheetFunction.Round(price * qty, 2)

Application.WorksheetFunction.RoundApplication.Round とも書けます)は、VBA から呼び出す ワークシー トの ROUND です。ですから端数を 0 から離れる向きに丸め、合計は 1 セント単位でぴたりと合います。目安は 身も蓋もありません。お金、そしてシートと一致しなければならない数値はすべて → WorksheetFunction.Round。 ネイティブの Round は、偶数への丸めこそが目的となる統計用途にとっておく。

丸めと切り捨ては違う:Int と Fix

丸めは端数をどちらへ動かすかを決めます。ですが、そもそも端数がいらず、ばっさり落としたい ときもありま す。それが切り捨てで、VBA にはそのための関数が二つあります — そして案の定、負の数では互いに食い違います。

Debug.Print Int(2.7)     ' 2    Fix(2.7)   ' 2    - 正の数では同じ
Debug.Print Int(-2.7)    ' -3   Fix(-2.7)  ' -2   - 負の数で分かれる

Int は負の無限大に向かって 切り下げます(真の床関数)。ですから Int(-2.7)-3 です。Fix0 に向かって 丸めます(小数部を落とすだけ)。ですから Fix(-2.7)-2 です。正の数では両者は同じ ですが、負の数が現れた瞬間、自分がどちらのつもりだったかを知っていなければなりません。どちらも Round ではありません — 端数を見て判断することは一切なく、ただ取り除くだけです。

また、VBA には組み込みの RoundUpRoundDown もありません。小数点以下の桁に対して「常に切り上げ」 「常に切り下げ」が必要なときは、ワークシート版に手を伸ばしましょう — Application.WorksheetFunction.RoundUp(x, 2)RoundDown(x, 2) です。

浮動小数点の脚注

すべての丸めの底には、もう一つの驚きが潜んでいます。Double の値は 2 進数で格納されるため、見た目のきれ いな小数の中には、正確に表現できないものがあるのです。古典的な例が Round(2.675, 2) で、返るのは 2.68 ではなく 2.67 です — 2.675 は実際には 2.67499999... として保持されており、そもそも本当の中 間の値ではないからです。これは Round のバグではなく、浮動小数点の性質です。1 セント単位の正確さが問題 になるときは、Currency 型か Decimal 型で計算するか、こうした表現の隙間をならすために作られた WorksheetFunction.Round を通して丸めましょう。

銀行丸めが正しい選択になるとき

これはどれも、VBA の Round が壊れているという意味ではありません — 別の仕事に向けて作られている、とい う意味です。平均や統計の集計、あるいは何千もの中間の値がなければ結果を上向きに偏らせてしまうような計算 をしているなら、偶数への丸めこそが 正しい 選択であり、ワークシートの「0 から離れる向き」の規則のほう が偏っています。そこでは意図的にネイティブの Round を使いましょう。間違いは Round を使うことではあ りません — 二つの規則が静かに食い違う場所、つまり表計算と帳尻を合わせなければならないお金に、それを使う ことなのです。

ExcelMaster の活用

丸めは、静かな三つの分かれ道を持つ判断です — 偶数への丸めか 0 から離れる向きか(ネイティブの RoundWorksheetFunction.Round か)、丸めか切り捨てか(RoundIntFix か、そしてそれらは負の数で食 い違う)、そして浮動小数点がそもそも本物の中間の値を保持しているのか。どの曲がり角を間違えても、静かに 失敗します — 合計が 1 セントずれる、負の数が間違った向きに切り下げられる、2.675 が切り上がらない、と いった具合です。

ExcelMaster には、本当に望むことをそ のまま伝えられます — 「各行を小数点以下 2 桁に丸めて、合計がシートの ROUND 列と一致するようにして」 — すると、あなたが シートに合わせて と言ったからこそ WorksheetFunction.Round を選び、切り捨てのつもり なら意図的に IntFix を使い、Double にお金を入れる罠を、1 セントの損も出さないうちに指摘しま す。ブックとコードはあなたの手元に残ります。

よくある質問

VBA の Round(2.5) はなぜ 3 ではなく 2 を返すのですか?

VBA の Round が銀行丸め — 最近接偶数への丸め — を使うからです。値がちょうど中間にあるとき、いちばん 近い偶数の桁へ向かうので、Round(2.5)2(2 は偶数)、Round(3.5)4(4 は偶数)になります。 ワークシートの =ROUND(2.5,0) は別の規則、つまり 0 から離れる向きの丸めを使うので 3 になります。名前 は同じ、規則は別です。

VBA でワークシートの ROUND と同じように丸めるには?

ワークシート関数を VBA から呼び出します — Application.WorksheetFunction.Round(x, 2)(または Application.Round(x, 2))。これはセルの =ROUND() とまったく同じく端数を 0 から離れる向きに丸めるの で、マクロで計算した合計がシートの ROUND 列と帳尻が合います。ネイティブの Round は、偶数への丸めが 本当に望みである場合のためにとっておきましょう。

VBA で小数点以下 2 桁に丸めるには?

第 2 引数に桁数を渡します — 銀行丸めなら Round(value, 2)、シートに合わせるなら Application.WorksheetFunction.Round(value, 2) です。小数点以下 2 桁まで常に切り上げる/切り下げるには、 WorksheetFunction.RoundUp(value, 2)RoundDown(value, 2) を使います — VBA にはネイティブの RoundUpRoundDown もありません。

VBA の Int と Fix の違いは?

どちらも小数部を取り除きますが、負の数で食い違います。Int は負の無限大に向かって切り下げるので Int(-2.7)-3 です。Fix は 0 に向かって切り捨てるので Fix(-2.7)-2 です。正の数では両者 は同一です。どちらも丸めません — Round と違い、小数を見て判断するのではなく、 捨てるだけです。

Round(2.675, 2) はなぜ 2.68 ではなく 2.67 になるのですか?

2.675Double として正確に格納できないからです — 実際には 2.67499999... として保持されるため、 本物の中間の値ではなく、切り下げられます。これは浮動小数点の表現であって、丸めのバグではありません。お 金には Currency 型か Decimal 型を使うか、Application.WorksheetFunction.Round を通して丸めましょ う。

検証環境

動作確認: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-09-18.

関連ガイド: VBA Mod · VBA Rnd · VBA Format · VBA 表示形式 · VBA WorksheetFunction