500円引きを、商品ごとにどう分けるのか — 注文全体の割引を比例配分して切り捨てたときに残る端数をどう置くかの図解
会員システムを使う人の、大人の算数・国語・論理的思考

お金を扱う大人の算数、第7回。今回は、注文全体の500円引きを、商品ごとの明細へ分けるときに何が起きるのかを見ていきます。

今回のテーマ

注文全体の500円引きを、商品ごとの明細へどう分けるのか。分けた合計は、500円になるのか。

要点先に、この回の要点

注文全体の500円引きを商品ごとに配分すると、割り切れず小数が出て、丸めると合計が498円などになって注文全体と一致しません。残った1〜2円をどの商品へ置くかまで決めて、初めて配分方法が仕様として完成します。

  • 均等配分/金額割合配分など方法はあるが、いずれも丸めで端数が出て合計がずれる(第1回と同じ問題)。
  • 「金額の割合で分ける」だけでは不十分。丸めたあとの余りをどの商品へ置くか(端数の大きい商品から等)のルールが要る。
  • 画面に商品別割引を見せなくても、後の返品・部分処理で必要になるため、購入時の配分を記録しておく。

注文全体から500円を引く。それだけなら、計算は簡単です。しかし、商品ごとの明細にも割引後の金額を出そうとすると、別の問題が生まれます。

500円を、どの商品から何円ずつ引くのか。

今回は、注文全体の割引を商品ごとへ分ける方法を考えます。

ここから数回は、同じ一つの注文を最後まで追いかけます。
割引のときには合っていた数字が、配分・返品・再注文・集計へ進むと、どう変わっていくのかを見るためです。

3つの商品を500円引きする

次の注文を例にします。

1 今回の注文
商品A:税込1,000円
商品B:税込1,000円
商品C:税込1,001円
商品合計3,001円
2 注文全体で500円引き
3,001円 − 500円 = 2,501円
注文全体の割引後金額。ここまでは、誰が計算しても同じです。
割引後金額2,501円

問題は、500円を3つの商品へどう分けるかです。

均等に分ける

まず、商品数で均等に分ける方法があります。500円 ÷ 3商品 = 約166.66円。円単位にするため、たとえば次のように分けます。

A 均等に分ける
商品A:167円引き → 833円
商品B:167円引き → 833円
商品C:166円引き → 835円
割引合計 167+167+166500円

割引後の合計は833円+833円+835円=2,501円となり、注文全体の割引後金額と一致します。ただし、均等配分では、商品の価格差を考えていません。今回は3商品がほぼ同じ価格なので大きな違和感はありませんが、100円の商品と1万円の商品が同じ注文に入っていても、同じ金額を割り引くことになります。

商品金額の割合で分ける

もう一つは、商品価格の割合に応じて500円を分ける方法です。

B 金額の割合で分ける
商品A:500 × 1,000 ÷ 3,001 = 約166.61円
商品B:500 × 1,000 ÷ 3,001 = 約166.61円
商品C:500 × 1,001 ÷ 3,001 = 約166.77円
小数のままなら約500円

商品価格の割合に沿っているため、均等配分より自然に見えます。しかし、0.61円や0.77円をそのまま割引額にはできません。円単位へ直す必要があります。

すべて切り捨てると、498円になる

それぞれの割引額を切り捨てると、商品A・B・Cとも166円になります。

比例配分して切り捨てると
商品ごとの割引を合計(166+166+166)498円
注文全体の割引500円
差 = 2円 500円引きのはずが、商品ごとへ分けたら498円引きになった。

ここでも、第1回と同じことが起きています。

部分ごとに丸めた合計と、全体の金額は一致するとは限りません。

注文全体では500円という一つの金額です。しかし、商品ごとへ分けると小数が生まれます。その小数を丸めたことで、2円の差が生まれました。

残った2円を、どこへ置くのか

498円のままでは、注文全体の500円引きと一致しません。そこで、残った2円を、どこかの商品へ加える必要があります。たとえば、

どちらも合計は500円です。注文全体では、どちらも正しく500円引きです。しかし、商品ごとの割引額は違います。つまり、

「金額の割合で分ける」と決めただけでは、まだ仕様は完成していません。

丸めたあとに残った1円や2円を、どの商品へ置くのか。そこまで決める必要があります。

実際に、余りをどこに置くか試せます——

端数の大きい商品から配る

一つの方法は、小数部分が大きい商品から、残った1円を配る方法です。今回の小数部分は、商品Aが0.61円、商品Bが0.61円、商品Cが0.77円。最も端数が大きい商品Cへ、まず1円を加えます。

残りの1円は、商品Aか商品Bへ加えます。しかし、商品Aと商品Bは、どちらも0.61円です。この場合は、さらにルールが必要です。

同じ端数が並んだときのルールの例
  • 明細の上から順
  • 商品番号の小さい順
  • 金額の大きい順

どの方法を選んでも構いません。ただし、同じ注文を計算すれば、毎回同じ結果になる必要があります。

「余りをどうするか」も仕様です

システムでは、「500円を商品価格の割合で分ける」と書いただけでは足りません。少なくとも、次のことを決める必要があります。

配分の前に決めておくこと
  • 均等に分けるのか
  • 金額の割合で分けるのか
  • 円未満を切り捨てるのか
  • 四捨五入するのか
  • 残った差額をどの商品へ入れるのか
  • 同じ端数の商品があった場合、どちらを優先するのか

割り算の式だけでは、最終結果は一つに決まりません。余りの置き場所まで決めて、初めて配分方法が完成します。

なぜ商品ごとに分けるのか

お客様の画面に、商品合計3,001円・クーポン割引500円・支払額2,501円とだけ表示するなら、商品ごとの割引額は見えません。それでも、内部では配分が必要になることがあります。

商品ごとの配分が必要になる場面
  • 商品ごとの売上を集計する
  • 商品別の利益を確認する
  • 明細ごとの割引後金額を帳票へ出す
  • 商品ごとの税額を計算する
  • 一部の商品だけを返品する

見せていないから、決めなくてよいわけではありません。後から商品単位の処理をするなら、購入時にどのように500円を分けたかが必要になります。

誰が決め、何が計算され、何を残すのか

「余りをどうするか」を仕様にするとは、次の三つを分けて決めることです。計算式そのものより、この切り分けのほうが実務では重要になります。

人が決めること
  • 均等配分か、比例配分か
  • 余った1円・2円をどの商品へ置くか
  • 端数が同値のときの優先順位
システムが計算すること
  • 決められた割合で配分する
  • 指定された単位で丸める
  • 残額を規則どおり加算する
記録として残すこと
  • 元の割引額(500円)
  • 配分後の各明細の割引額
  • 端数を加えた商品
割引配分を、仕様書の言葉にすると

500円を、商品ごとに分ける。

注文割引額は各明細の税込金額比率により按分し、1円未満を切り捨てる。配分残額は小数部の大きい明細から1円ずつ加算し、同値の場合は明細番号順とする。

同じ「500円を分ける」でも、上の一文まで書けば、誰が処理しても同じ配分が再現できます。曖昧な言い方と、仕様書にした言い方の差は、この再現性にあります。

現場では、こうなる

明細ごとの割引額を聞かれても、担当者によって答えが違う。同じ注文なのに、説明が一つに定まらない。

今回、覚えておきたいこと
設計の第7段 / 12 ・ 配分規則を決める
全体を部分へ分けるときは、余りの置き場所まで決める。

注文全体の500円引きを、商品ごとへ分ける。簡単な割り算に見えます。しかし、商品ごとに分けると小数が生まれ、比例配分した金額をすべて切り捨てると、500円引きのはずが、498円引きになりました。足りない2円をどの商品へ入れるかによって、商品ごとの割引後金額も変わります。余りの2円をどこへ置くかに、唯一の正解があるわけではありません。重要なのは、同じ注文なら誰が処理しても同じ配分を再現できることです。正しい計算を一つ選ぶのではなく、再現できる計算を決める。それが、注文全体の割引を商品ごとへ分けるときに必要な設計です。

Series ・ 特別編 大人の算数・国語・論理的思考 ― 連載一覧へ

よくあるご質問(FAQ)

Q注文全体の割引を商品ごとに分けると、なぜ合計がずれるのですか?
A

割り切れず小数が出て、それを円単位に丸めるためです。全部切り捨てると498円のように、注文全体の500円引きと一致しなくなります。

Q「金額の割合で分ける」と決めれば十分ですか?
A

不十分です。丸めで残った1〜2円をどの商品へ置くか(余りの置き場所)まで決めないと、商品別の割引額が一意に決まりません。

Q余りはどの商品に加えるのが正解ですか?
A

唯一の正解はありません。端数の大きい商品から配る等の方法を決め、同じ注文なら毎回同じ結果になるようにします。同点の場合の順序も決めておきます。

Q商品別の割引を画面に出さないなら、配分は決めなくてよいですか?
A

いいえ。後から返品や部分処理を行うとき、購入時にどう配分したかが必要になります。見せなくても記録しておくべきです。

岸本 健志
会員ビジネスLab 主任研究員 / ハートランドITイノベーション代表

1997年よりインターネット業界に従事。2007年の創業以来、EC、メディア、SaaS、コミュニティサイトなど数多くの会員ビジネスの立ち上げと成長を支援。

30年近く会員システムの設計・運用に携わる中で、仕様は画面や機能だけでは完成せず、金額・言葉・条件という「基礎」をそろえて初めて一つに決まると考えるようになりました。この特別編では、その基礎を大人の算数・国語・論理的思考として整理しています。

「人との関係は設計できるのか」という問いに、これからも愚直に向き合い続けていきます。

← 大人の算数・国語・論理的思考 連載一覧へ