現場

値段が決まる場所はひとつ — ラベルと帳簿が締めでずれる理由

著者: makemind · 2026年8月4日

量り売りの店は いつか締めが合わなくなる。

ラベルの束を足した額とレジ合計が数百円ずれ、どこで出たのか見つからない。しかも毎日少しずつ出る。

なぜ出るのか

値段が 二度 計算されるからだ。

  • ラベルを打つとき — 客が払える単位に丸める。3,444.5 円のものを 3,440 円と打つ。
  • 帳簿に入れるとき — 重さから計算し直す。3,444.5 円。

どちらも間違っていない。ところが違う。そしてその差は一件あたり 4〜5 円なので、一日経たないと見えない。

値段を作る場所をひとつに

このサンプルの答えは関数ひとつだ。

/// The only place a price is made.
///
/// Rounds to what somebody can pay, once. Every other number in this server
/// — the label, the ledger, the day total — comes from this and never from
/// a second pass over the weight.
static int priceFor(Product p, int grams) {
  final exact = p.wonPer100g * grams / 100;
  return (exact / _payableStep).round() * _payableStep;
}

そしてラベルを打つとき、その一度の結果がそのまま帳簿に入る。

// One call, one number. The label and the ledger row are the same
// integer, so there is nothing for them to disagree about.
final won = priceFor(_product, _grams);
_sales.add(Sale(_product.code, _product.name, _grams, won));

客が払った額が、そのまま帳簿に残る額だ。 帳簿が「本来は 3,444.5 円だが」と言う理由は無い — 客はそれを払っていない。

はかりの上

Pork belly 2980 won/100g — 347 g. LABEL 10340 won, exact 10340.6 · rounded -0.6 won to the nearest 10
Pork belly 2980 won/100g — 347 g. LABEL 10340 won, exact 10340.6 · rounded -0.6 won to the nearest 10

ラベルに 丸めがいくらだったかが書いてある。

pan: Pork belly 347 g — exact 10340.6 won, label 10340 won (rounded -0.6 won to the nearest 10)
// What the rounding actually did, in won, said out loud. A shop
// that rounds without showing it is a shop that argues later.

これは客のためではなく 店のためのものだ。丸めを見せなければ、後で「なぜこの計算になるのか」と聞かれて誰も答えられない。見せてあればその場で終わる。

五件、そして締め

label 1:  347 g -> 10340 won   (exact 10340.6, rounded -0.6)
label 2:  512 g -> 21250 won   (exact 21248.0, rounded +2.0)
label 3:  210 g ->  2600 won   (exact  2604.0, rounded -4.0)
label 4: 1000 g -> 29800 won   (exact 29800.0, rounded  0.0)
label 5:   83 g ->  3440 won   (exact  3444.5, rounded -4.5)

切り上げも切り下げもぴったりもある。 わざとそう選んだ — 全部同じ方向に丸まるデータで試すと、この種のバグは捕まらない。

TODAY · 5 LABELS — 67430 won
TODAY · 5 LABELS — 67430 won
ledger says 5 labels, total 67430 won
harness added the labels itself: 67430 won
ledger total minus watched labels: 0 won

このコンテンツは開発者以上が必要です

サインインしてプランをアップグレードすると続きを読めます。

プランを見る
Twitter