周末在给儿子辅导作业时,注意到他在算 450÷10 时几乎不假思索,但遇到 450÷6 时立刻眉头紧锁,这让我突然意识到一个我们习以为常,却很少认真想过的问题:

为什么在算乘除 10 的幂时,我们几乎完全不需要思考,而换成别的数就特别费劲呢?

加上前段时间和儿子一起探究 Positional Numeral System,想到这里,突然让我茅塞顿开 —— 这不就是 10 进制的位移操作嘛!

为什么乘/除 10 不需要思考?

来看一个我们从小就会的操作:

1
2
45 × 10 = 450
450 ÷ 10 = 45

你在做什么?

你并没有在算:

1
45 × 10 = 10 + 10 + 10 ……

你做的是 —— 把所有数字整体向左或向右移动一位

这不是“计算”,而是位置重排。

只不过我们从小接受的义务教育从来就没有提到「位移」这个概念,老师只是告诉你:

  • 乘 10 的结果就是在被乘数后面补 1 个 0
  • 乘 100 的结果就是在被乘数后面补 2 个 0
  • 乘 1000 的结果就是在被乘数后面补 3 个 0
  • 以此类推……

位移真的不是巧合吗?

如果你对这个结论还有疑问,那咱们不妨用数学的方式来证明一下这并不是巧合。

在十进制中,一个数可以表示为:

两边同时乘以

结合 Place Value (位值),我们可以对比一下乘 前后,每个「位」的 Place Value 的变化:

Place x10 前 x10 后
万位 10,000 10,000,000
千位 2,000 2,000,000
百位 300 300,000
十位 40 40,000
个位 5 5,000

由此可见,确实是每个「位」都往前移了 3 位。

位移不是二进制的专属

对于学过编程的人,一提到「位移」,立刻就想到了:

  • << → 左移
  • >> → 右移

在二进制中,经常会将乘/除 2 的幂写成位移操作,例如,计算矩形水平方向上的中心点:

1
int centerX = width >> 2;

在 2 进制中,「往右移 1 位」等价于「除以

1
int centerX = width / 2;

而往「往右移 2 位」等价于「除以

到这里大家有没有发现一个规律:

  • 在 10 进制中,乘/除 10 的幂等价于位移操作
  • 在 2 进制中,乘/除 2 的幂等价于位移操作

那么问题来了:

我们是不是可以将这个规律推广到任何进制?即:

「乘以基数的 n 次方」等价于「左移 n 位」
「除以基数的 n 次方」等价于「右移 n 位」

Radix Shit

没错,这个结论在任何位值制系统中都能成立,这也正是基于 Positional Numeral System 的一个重要推论 —— Radix Shift

只不过,这个概念从来没有被单独被提及,而是分散在各个语境里:

  • 小学算术:它被刻意包装成「技巧」,而不是「结构」
  • 计算机科学:它被重新包装命名为 —— bitwise shift
  • 信号处理:它又被命名为 —— scaling
  • IEEE 754:它又被冠以新的名词 —— exponent

那为什么“别的数”就很难?

因为,当乘/除的数不是进制的基数时,就无法只「移动位置」,只能回到:

  • 乘法分配
  • 加法叠加

这些都是算术层面的计算,而不是结构层面的变换。

换句话说,在任何进制中:

  • 乘/除基数 (radix) → 在操作「表示法」
  • 乘/除别的数 → 在操作「数值本身」

前者是结构变换,后者只是数值计算。