数学 / 函数 · 从概念到零点与增长速度 / 对数函数 y = logₐ x:指数函数的反函数 待审核 9 / 12
logarithm · y=logaxy = \log_a x · axa^x 的反函数

对数函数 y=logaxy = \log_a x:指数函数的反函数

对数函数(logarithmic function)y=logaxy = \log_a x指数函数 y=axy = a^x 的反函数(a>0a > 0a1a \ne 1)。指数函数把 xx 送到 axa^x,对数函数把它送回来,两条互逆的等式是 loga(ax)=x\log_a(a^x) = xalogax=xa^{\log_a x} = x

1 · 反函数关系与图象的镜像

y=logaxy = \log_a x · 关于 y=xy = x 镜像 · (1,0)(1, 0)

互为反函数在几何上表现为图象关于直线 y=xy = x 对称:指数曲线上的点 (x,ax)(x, a^x) 与对数曲线上的点 (ax,x)(a^x, x) 横纵坐标互换,两点关于 y=xy = x 互为镜像。

定义域与值域随之互换。指数函数的定义域是 R\mathbb{R}、值域是 (0,+)(0, +\infty),对数函数正好反过来:定义域 (0,+)(0, +\infty)、值域 R\mathbb{R}。真数必须为正这一条不是额外规定,而是由 axa^x 恒为正推出来的。对数曲线恒过定点 (1,0)(1, 0),对应指数曲线过 (0,1)(0, 1)

单调方向则不互换,两者一致:a>1a > 1 时同为递增,0<a<10 < a < 1 时同为递减。这是因为反函数保持单调方向——把图象沿 y=xy = x 翻转不改变「升」还是「降」。

图 1-1 · 同一坐标系里的指数曲线、对数曲线与直线 y=xy = x,虚线连接互为镜像的两点。可拖动底 aa 观察两条曲线如何同步改变单调方向。

常用的底有两个:1010 记作 lg\lg,自然底 ee 记作 ln\ln。有了换底公式,任何底的对数都能由这两者算出,所以计算器只需提供这两个键。

2 · 换底公式在浮点下不是恒等式

float · lg1000ln1000/ln10\lg 1000 \ne \ln 1000 / \ln 10

换底公式 logaN=logcN/logca\log_a N = \log_c N / \log_c a 在数学上是恒等式,两端是同一个实数。浮点下不是:等式两端走的是不同的计算路径,各自的舍入没有理由抵消。

最短的例子是 log101000\log_{10} 1000。原生实现 Math.log10(1000) 返回精确的 3,而按换底公式算的 Math.log(1000) / Math.log(10) 返回 2.9999999999999996,差一个 ulp。这个差别足以让 Math.log(1000) / Math.log(10) === 3 为假,而这条判等在「求 100010001010 的几次幂」这类整数问题里是会被写出来的。

偏差的多寡与底有关,实测差得很远。取 22 的幂 2k2^kkk116060),Math.log2 全部 6060 个都返回精确的整数,而换底算法有 88 个不精确,最大误差 7.11×10157.11 \times 10^{-15},出现在 k=39k = 39。换成 33 的幂 3k3^kkk114040),换底算法有 3232 个不精确,比例从 13%13\% 跳到 80%80\%(node v26.6.0)。

注 · 22 这个底之所以好得多,是因为 Math.log2 通常由硬件或专门的算法直接给出,不经过一次除法;而 22 的幂在二进制里是精确的,取对数只需读阶码。33 的幂在二进制下没有这种结构,ln3\ln 3 本身又要先舍入一次,于是分子分母各带一次误差。这也解释了 JavaScript 为何在 Math.log 之外单列 Math.log2Math.log10——不是记号方便,是精度不同。

3 · 参考文献

  1. Logarithm. Wikipedia. 对数的定义、运算法则与换底公式。https://en.wikipedia.org/wiki/Logarithm
  2. Inverse function. Wikipedia. 反函数的定义、图象对称与单调方向的保持。https://en.wikipedia.org/wiki/Inverse_function
  3. Math.log2. MDN. 单列 22 为底的对数方法及其精度理由。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log2