Excel
VBA
消費税

消費税8%で端数処理をするにはどうするか

消費税の出し方

税法上は1.08で割る。
端数処理は任意。
というのが原則のようです。
任意といっている場合、切り捨てが原則です。だって一番安くなるから。
これがわからない人はもうここから先読まなくていいです。
しかしながら、切り捨ては、戻すときに戻らなくなる気もします。

ここで税込み価格A円の商品があります。
これを1.08で割ります。
端数処理は四捨五入か切り捨てします。
これをX円とします。
X円×1.08をします。
これをまた四捨五入か切り捨てします。
これは組合せは四通りありますね。
それではこの組み合わせの中でどれが一番元に戻るのでしょうか。

Excelマクロ

MakeNumberLine
Sub MakeArrayFormColumn()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = ActiveSheet
Dim irow As Long, i As Long, icol As Long
Dim LastRow As Long, LastCol As Long
Dim buf As String
LastCol = ws.Cells(1, Columns.Count).End(xlToLeft).Column
Debug.Print LastCol
For i = 1 To LastCol
buf = buf & ws.Range(Cells(1, i).Address).Value & ";"
Next i
Debug.Print buf
End Sub
Sub titlerowarray()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = ActiveSheet
Dim irow As Long, i As Long, icol As Long
Dim LastRow As Long, LastCol As Long
Dim buf As String
Dim ar, iar As Long
Application.Calculation = xlCalculationManual
Application.DisplayAlerts = False
Application.ScreenUpdating = False
ar = Split("整数;A/1.08;Round(B);Round(C*1.08);D-A;INT(B+0.5)(:F:); INT(B);B*1.08(:H:); F*1.08(:I:); G*1.08(:J:); Int(I+0.5)(:K:); Int(I);Int(J+0.5);Int(J);MATCH(A,K:N,0);$A-K;$A-L;$A-L;$A-N", ";")
i = 1
For iar = LBound(ar) To UBound(ar)
ws.Cells(1, i).Value = ar(iar)
i = i + 1
Next iar
Range("P:Q, K:L, F:F, I:I").Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
Range("G:H,M:N,R:S").Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent5
.TintAndShade = 0.799981688894314
.PatternTintAndShade = 0
End With
For irow = 1 To 100000
ws.Activate
icol = 1
ws.Cells(irow + 1, icol).Value = irow: icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=A" & irow + 1 & "/1.08": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=ROUND(B" & irow + 1 & ",0)": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=ROUND(C" & irow + 1 & "*1.08,0)": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=D" & irow + 1 & "-A" & irow + 1: icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=INT(B" & irow + 1 & "+0.5)": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=INT(B" & irow + 1 & ")": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=B" & irow + 1 & "*1.08": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=F" & irow + 1 & "*1.08": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=G" & irow + 1 & "*1.08": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=INT(I" & irow + 1 & "+0.5)": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=INT(I" & irow + 1 & ")": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=INT(J" & irow + 1 & "+0.5)": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=INT(J" & irow + 1 & ")": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=MATCH(A" & irow + 1 & ",K" & irow + 1 & ":N" & irow + 1 & ",0)": icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=$A" & irow + 1 & "-K" & irow + 1: icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=$A" & irow + 1 & "-L" & irow + 1: icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=$A" & irow + 1 & "-M" & irow + 1: icol = icol + 1
ws.Cells(irow + 1, icol).Formula = "=$A" & irow + 1 & "-N" & irow + 1: icol = icol + 1

Next irow
irow = ws.Cells(Rows.Count, 1).End(xlUp).Row
Range("A1").Select
Selection.End(xlDown).Select
Range("S" & irow).Select
Range(Selection, Cells(1)).Select
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
With Selection.Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
With Selection.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
With Selection.Borders(xlInsideVertical)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
With Selection.Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.ColorIndex = 0
.TintAndShade = 0
.Weight = xlThin
End With
Application.Calculation = xlCalculationAutomatic
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Application.Calculate
End Sub

これで計算すると20円以上で次の4種類の数列の数字が表れます。
このうち問題になるのは太字のものです。
a>20
nは1以上の自然数とします。
完全数 27+(n-1)*27 >>> 27n 270 (250)
これは切り捨て、四捨五入に影響されません。

*Matchが2 20+(n-1)*27 >>> 27n-7 263 (243.5) 243 *1.08 =262 四捨五入、四捨五入だと1多くなる*
切り捨てで2違う 14+n*27 >>> 27n+14 257(237.9) 237*1.08= 255.96 四捨五入、四捨五入だと問題ない
*N/A数 34+(n-1)*27 >>> 27n+7 277 (256.48) 256*1.08= 276.48 四捨五入、四捨五入だと1少なくなる*

ちなみに10万までの差を合計すると
間違いを積み上げると
1.08で割って1.08で戻すときにともに四捨五入するときが一番少なく、ともに切捨てが一番多い
1 48146 51855 100001 
これはマイナスになる場合もあるからです。それでは個数ではどうでしょうか。
間違う個数もともに四捨五入が一番少なく、10万中7407 1%以下
7407 48146 51855 96297 =COUNTIF(P2:P100001,"<>0")
税抜きにするとき四捨五入 税込みにするとき四捨五入
この数列の関係は10万まで調べても変わらないので、これ以上になっても変わりません。(消費税が1.08で3ケタのため)
結論として、機械的に処理すると表示においては、税抜きから税込みにするときともに四捨五入するときが一番誤差が少ない。
ということになります。
切り捨てにすると税金はやすくなりますが、いきなり誤差が積みあがります。

10%の場合はどうか

5円以上では
完全数 11n
ともに四捨五入で1足りなくなる数
11n-6
となります。つまり問題になるのは1種類だけで11n-6の数列に入る数です。
このため8%のときより
誤差の合計
-9091
誤差の個数
9091
になります。つまり-1になるものしかなくそれが11n-6だということです。