🧠 第三章 编程语言
📄 一句话概括

同一句「按档算」有两种理解:全额跳档和分段累进。 多卖 1 元,跳档算法多给 300.08 元,累进只多 0.08 元。 200 个档位合计,两种算法差 657000 元。

📝 本节和前面几节的关系

上一节把循环讲完,这一节用循环算一张真实的奖金表。这是本书第一个「算错了会被人找上门」的实例。

一、两种理解,差一台电脑

规则写的是:1 万以内 5%,1 到 5 万 8%,5 到 10 万 12%,超 10 万 15%。这句话有歧义。 - 全额跳档:整笔业绩按它所在的档位算。8 万就全部按 12% 算。 - 分段累进:每一段只用自己那一档的税率。8 万=1 万按 5%、4 万按 8%、3 万按 12%,加起来。 Demo 把两种都实现了一遍,同一个 8 万:跳档给 9600,累进给 7300,差 2300 元。 这不是算术问题,是口径问题。口径没定,代码写得再对也是错的。

二、断崖:多卖一块钱多拿三百

跳档算法在档口会断崖。 Demo 算得很清楚:业绩从 10000 涨到 10001,提成从 500 跳到 800——多卖 1 块钱, 提成多 300.08 元。 累进算法同一位置只多 0.08 元,是一条连续的线。 断崖带来什么后果?业绩卡在 9900 的人会想办法凑到 10100;卡在 49900 的会想办法凑到 50100。 规则本身在激励凑单。 累进算法没有这个问题,因为每多一块钱都只多那 1 块钱对应的比例。 这也是为什么正规的个税、阶梯电价都用累进。

三、把两百个档位合计一遍

Demo 从 1000 到 200000 每隔 1000 取一个点,一共 200 个,两种算法都算一遍。 结果:跳档合计 2810850 元,累进合计 2153850 元,公司多付 657000 元。 65 万这个数字,比任何一句「差得不多」都有说服力。谈规则的时候,拿这张表出去,比讲道理管用。 注意这里的 200 个点是我为了演示取的等间隔值,不是真实业务分布。 真实数据要先拉出业绩分布,再按分布算——等间隔取样会高估高业绩档的权重。

四、写这类代码的固定套路

看一眼 Demo 的分段累进实现,结构是固定的: 1. 把档位写成一个列表:(段宽, 税率)。 2. 从左到右遍历,每段取 min(剩余, 段宽)。 3. 减掉用掉的额度,用完就 break。 最后一个档位宽度写一个极大值(比如 1e18),表示「剩下的全归这档」。这样不用特判,循环自己会收敛。 这个套路能直接套到阶梯电价、个税、物流阶梯运费、云服务阶梯计价——凡是「分段累进」的规则, 代码长得一模一样。

五、动手 Demo:算业绩提成,两种算法差出一台电脑

把两种口径各写成一个函数,对 9 个业绩点逐一算出两边的提成和差额; 再算档口处「多卖 1 元」的提成增量; 最后从 1000 到 200000 每 1000 取一个点,合计 200 个档位,比较两种算法的总额。

def step_full(x):        # 全额跳档
    if x <= 10000:   return x * 0.05
    if x <= 50000:   return x * 0.08
    if x <= 100000:  return x * 0.12
    return x * 0.15

def step_part(x):        # 分段累进
    bands = ((10000, 0.05), (40000, 0.08),
             (50000, 0.12), (1e18, 0.15))
    left, tot = x, 0.0
    for width, rate in bands:
        take = min(left, width)
        tot += take * rate
        left -= take
        if left <= 0:
            break
    return tot

实跑输出:

--------------------------------------------------------------------
实例 1:算业绩提成,两种算法差出一台电脑
--------------------------------------------------------------------
  规则                     1 万以内 5%,1~5 万 8%,5~10 万 12%,超 10 万 15%

    业绩   全额跳档   分段累进   差额
  ----------------------------------
    8000        400        400      0
   10000        500        500      0
   10001        800        500    300
   30000       2400       2100    300
   50000       4000       3700    300
   50001       6000       3700   2300
   80000       9600       7300   2300
  100000      12000       9700   2300
  200000      30000      24700   5300

  多卖 1 元,跳档算法多给  300.08 元
  多卖 1 元,累进算法多给  0.08 元
  跳档算法在档口会「断崖」:多卖 1 块钱,提成多 300 块。
  累进算法永远是连续的一条线。做奖金表必须先问清是哪一种,
  同一句「按档算」,两种理解在 5 万这一档差 300 元。

  200 个档位合计(跳档)   2810850 元
  200 个档位合计(累进)   2153850 元
  公司多付                 657000 元

九行对照表里,差额全是 0、300、2300、5300 这几个数——每一档刚跳过去时差额最小,越往上差得越多。 注意到 10000 和 10001 两行:跳档从 500 直接到 800,累进从 500 到 500。这就是断崖的现场。 「多卖 1 元」那两行:跳档多 300.08 元,累进多 0.08 元。 300 倍差距,全在一个 if 的边界上。 5 万这一档两种理解差 300 元——注意这里跳档是 4000、累进是 3700。 同一句「按 8% 算」,落地成代码能差这么多。 200 个档位合计 2810850 对 2153850,差 657000 元。这个数就是口径没对齐的代价。

30 秒实验

  1. 把档位改成「3 万以内 5%、3 到 8 万 10%、超 8 万 15%」,两种算法重算一遍。
  2. 算一下:业绩 50000 和 50001,跳档算法的提成差多少?
  3. 想一想:为什么阶梯电价、个税都用累进而不用跳档?

常见误区

  1. 「按档算就是乘以那档的比例」——那只是一种理解,还有累进。
  2. 「差一点点不用管」——200 个档位差 65 万。
  3. 「取等间隔样本就够了」——真实业绩分布不是均匀的,会算偏。
自测三问(点开对答案) 1. 全额跳档和分段累进的区别是什么? —— 跳档整笔按所在档的比例算;累进每段只按自己那档的比例算。 2. 为什么跳档算法会产生「凑单」激励? —— 档口处多卖 1 元,提成会跳好几百,跨过去就赚。 3. 分段累进的代码为什么最后一档写极大宽度? —— 表示剩下的全归这档,不用特判,循环自然收敛。

奖金算完,下一个实例练排序——三种手写法和内置的差距会很明显。

相关笔记