实战

定价只发生在一处 — 标签和账本为什么在收档时对不上

作者: 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