ネットの海の片隅で

技術ネタの放流、あるいは不法投棄。

消費税つらい

これは何

消費税の端数処理がめんどくさすぎることについて、あーだこーだ言うだけのエントリ。

問題

あらためて言うまでもないかもしれないが、現在、この国では消費税というものがあって、一部の例外を覗いて、商品の価格に加えて8%の金額を税として支払う必要がある。 税抜100円のものを買うと、8%にあたる8円の税がかかって税込108円支払う必要がある。

値札に税抜価格を表示して精算時に税込価格を算出すれば良いケースであれば、その通りにすれば良い。

一方、値札に税込価格を表示したいケースではめんどくさくなってくる。

税込価格と税抜価格の変換

税込680円ののものは 680 / 1.08 = 629.6296... となり、税抜630円になる。すると、630 x 1.08 = 680.4 となり、四捨五入して税込680円になる。

同様に税込780円のものについて考えると 780 / 1.08 = 722.22... となり、税抜722円になる。すると、722 x 1.08 = 779.76 となり、四捨五入して税込780円になる。

合わせ買い

税込780円のものを3つ買うと税抜合計が 722 * 3 = 2166] 円になる。この税抜合計2166円に対して税込価格を算出すると 2166 x 1.08 = 2239.28 となり、四捨五入して税込2339円になる。「780円のものを3つ」買ったはずなのに!

同様に税込680円のものを3つ買うと税抜合計が 630 x 2 = 1260 円になる。この税抜合計1260円に対して税込価格を算出すると 1260 x 1.08 = 1360.8 となり、四捨五入して税込1361円になる。「680円のものを2つ」買ったはずなのに!

ここでは端数処理を四捨五入 round で扱ったが、切り上げ ceil や切り捨て floor にしても同じ問題が起こる。

問題の構造

消費税が8% (0.08) であることによって、素朴な掛け算だけでは計算結果が整数に閉じない。そこで、round/floor/ceil あたりの端数処理を加えることになるが、この端数処理のせいで分配法則が成り立たなくなる。

つまり、税抜価格から税込価格を算出する関数 f について一般には

f:id:s_osa:20190329110602p:plain

が成り立たない。

解決策

税抜価格算出時の端数処理を floor にする

合わせ買いしたときにお客さんが損をしないようにする。

つまり、

f:id:s_osa:20190329110632p:plain

が常に成り立つようにする。

メリットはお客さんが損をすることがない。 デメリットは「利益が減る」「1円のお釣りが発生するケースが増える」あたり。

税込価格ではなく「参考税込価格」などとしながら、実際に運用されているのもよく見かける。

個々の商品に対して税額計算する

右辺を使うようにする。

これができるケースならシンプルで良さそう。

税込・税抜の併記をやめる

一番シンプルっぽいが、この問題にぶつかってる時点でこの選択肢を取れる場合は少なそう。ただ、本当に無理なのか問い直してみる価値はある。

消費税率を変更する

消費税率が8% (0.08)だから素朴な掛け算の結果が整数に閉じない。

つまり、消費税率が整数(0%, 100%, 200%, ..., 100 * n %, ...)であれば、整数に閉じるようになる。

通貨を変更する

我々は暗黙のうちに通貨が整数として定義されていることを受け入れてしまっている。

通貨の定義域が有理数に拡張されれば、8%の消費税を掛けた結果も有理数に閉じる。

おわりに

現実世界はたいへん。 すべての物事を設計するときに simplicity 大切にしてほしい。

ガッと書いたので漏れなどあるかも。