news 2026/9/7 20:31:48

反比例函数的原函数为什么是ln|x|?微积分关键推导与Python验证

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
反比例函数的原函数为什么是ln|x|?微积分关键推导与Python验证

如果我问你:反比例函数 (y=\frac{1}{x}) 的原函数是什么?很多学过微积分的人会脱口而出:(\ln|x|+C)。但再追问一句“为什么”,不少人就停在“这是公式”的层面了。尤其是当公式被写成 (\int \frac{1}{x} dx = \ln|x| + C) 时,真正值得搞清楚的问题有三个:为什么幂函数积分规则在 (n=-1) 这里失效了?为什么填补这个空白的偏偏是自然对数?以及为什么结果必须带绝对值?

这个问题看起来很小,但它其实是微积分里“函数类闭环”的一个关键节点。把反比例函数、指数函数、对数函数、幂函数串起来的,正是导数和积分这对互逆关系。理解它,不仅对数学有用,对做算法、写代码、调数值积分的开发者同样重要。因为你会发现,很多程序库里的log、符号计算里的integrate、数值积分里的奇异点处理,都和这节课有关。

我打算用一条主线来拆:先看为什么 (1/x) 是幂函数积分规则里的特殊分子,再证明为什么对数函数的导数恰好是 (1/x),最后用 Python 和 SymPy 做验证,把容易踩的坑一次性讲清楚。

1. 先搞清楚:反比例函数、原函数与这个问题的真正难点

反比例函数,在初等数学里通常指形如 (y=\frac{k}{x})((k \neq 0))的函数。当 (k=1) 时,就是 (y=\frac{1}{x})。它的图像是双曲线,在 (x=0) 处不定义,并且当 (x \to 0^+) 时函数值趋于正无穷,当 (x \to 0^-) 时函数值趋于负无穷。这两条分支分别位于第一象限和第三象限。

原函数的定义也不复杂:如果函数 (F'(x)=f(x)),那么 (F(x)) 就是 (f(x)) 的一个原函数。不定积分 (\int f(x) dx) 表示 (f(x)) 的全部原函数,写成 (F(x)+C)。对 (y=\frac{1}{x}) 来说,我们要找的,就是导数等于 (\frac{1}{x}) 的那个函数。

真正难的地方在于:这个反比例函数图像很简单,可它的原函数并不是普通幂函数,而是一个“新函数” (\ln|x|)。许多初学者会被这个转折绊倒:明明 (1/x = x^{-1}),按照幂函数求积分公式不是应该得到“某个幂函数”吗?为什么跑出来一个看起来完全不同的对数函数?

我建议先放下“背公式”的思路,重新从求导的方向推导一次。因为原函数这个概念本身就是“求导的逆运算”,只要你能找到一个函数,它的导数确实是 (\frac{1}{x}),那你就找到了原函数。接下来我们要做的,就是证明 (\ln x) 和 (\ln(-x)) 的导数都等于 (\frac{1}{x})。

2. 1/x 为什么是幂函数积分规则里的“例外”

先回顾幂函数的求导公式:

[ (x^a)' = a x^{a-1} ]

把这条公式反过来看,求 (x^n) 的原函数时,我们会期望:

[ \int x^n dx = \frac{x^{n+1}}{n+1} + C ]

这个公式成立的条件是 (n \neq -1)。因为当 (n=-1) 时,分母 (n+1=0),分式没有意义。有人可能会想:如果硬写成 (\frac{x^0}{0}),那不就是“除以 0”吗?显然不行。

但更深的问题在于: ((\frac{x^0}{0})') 也不等于 (1/x)。事实上 (x^0 = 1) 的导数是 (0),不管前面乘什么常数,它都只能是 0,不可能是 (1/x)。所以,常规的幂函数原函数族里,根本没有 (x^{-1}) 的位置,必须引入一个新函数来补位。

这里有一个非常有启发性的视角。积分公式里的 (\frac{x^{n+1}}{n+1}) 在 (n) 趋近于 (-1) 时的极限,恰好能把我们引向 (\ln x)。我们这样做:设 (h = n+1),当 (n \to -1) 时 (h \to 0)。于是从 1 到 (x) 的定积分应该是:

[ \lim_{h \to 0} \frac{x^h - 1}{h} ]

这个极限的结果就是 (\ln x)。它是通过自然常数 (e) 的极限定义得到的,所以在“幂函数通式”和“对数函数”之间,并不是两条互不相干的路,而是一条路的极限状态。这也解释了为什么 (n=-1) 是个“临界点”:它不是一个简单的空白,而是一道通向对数函数的门。

3. ln 的来路:从指数函数反函数到自然对数

既然 (1/x) 的原函数不是普通幂函数,那它为什么偏偏是 (\ln x)?要回答这个问题,我们需要重新认识自然对数。

自然对数 (\ln x) 最常见的定义是:它是自然指数函数 (e^x) 的反函数。也就是说,如果 (y = \ln x),那么等价于 (x = e^y)。这里的 (e) 是自然常数,约等于 2.71828,最常见的定义是:

[ e = \lim_{n \to \infty} \left(1 + \frac{1}{n}\right)^n ]

从“指数函数反函数”这个定义出发,我们可以很快算出它的导数。设 (y = \ln x),则 (x = e^y)。两边对 (x) 求导:

[ 1 = e^y \cdot \frac{dy}{dx} ]

于是:

[ \frac{dy}{dx} = \frac{1}{e^y} = \frac{1}{x} ]

这个证明非常干净。它依赖的关键点是:(e^x) 的导数等于它本身。而 (e^x) 的这个性质,正好来自 (e) 的定义。所以说,(1/x) 的原函数是对数函数,不是偶然,而是因为“指数函数的反函数”天然地导出了“倒数”关系。

还有一本书会采取另一种定义方式,直接把 (\ln x) 定义为积分:

[ \ln x = \int_1^x \frac{1}{t} dt ]

这个定义对 (x>0) 成立。按照微积分基本定理,积分上限函数的导数就是被积函数,所以 (\ln x) 的导数等于 (\frac{1}{x})。这样一来,反比例函数的原函数是对数函数,几乎是定义本身的直接结果。

两种定义殊途同归。不管从哪条路走,你都会遇到同一个结论:对数函数是“倒数关系”的积分产物。这也正是“反比例函数的原函数是 lnx”这句话背后真正的数学结构。

4. 严格证明:(ln x)' = 1/x,以及为什么会出现绝对值

4.1 先用反函数求导法证明

前面已经写了反函数求导法的核心步骤,这里把它整理成完整证明。设:

[ y = \ln x ]

则:

[ x = e^y ]

对两边关于 (x) 求导,得到:

[ \frac{d}{dx}(x) = \frac{d}{dx}(e^y) ]

左边是 1,右边根据链式法则是 (e^y \cdot \frac{dy}{dx})。于是:

[ 1 = e^y \cdot \frac{dy}{dx} ]

由于 (e^y = x),所以:

[ \frac{dy}{dx} = \frac{1}{x} ]

这个证明只对 (x>0) 有效,因为 (\ln x) 本身只定义在正数区间。但它已经回答了“为什么 (1/x) 的一个原函数是 (\ln x)”。

4.2 用导数定义直证

如果你不想依赖反函数求导,也可以直接从导数的极限定义出发。

[ (\ln x)' = \lim_{h \to 0} \frac{\ln(x+h) - \ln x}{h} ]

利用对数运算法则:

[ \ln(x+h) - \ln x = \ln\left(\frac{x+h}{x}\right) = \ln\left(1 + \frac{h}{x}\right) ]

所以:

[ (\ln x)' = \lim_{h \to 0} \frac{1}{h} \ln\left(1 + \frac{h}{x}\right) ]

令 (t = \frac{h}{x}),当 (h \to 0) 时 (t \to 0),于是:

[ (\ln x)' = \frac{1}{x} \lim_{t \to 0} \frac{\ln(1+t)}{t} ]

这里的极限 (\lim_{t \to 0} \frac{\ln(1+t)}{t} = 1),正是由自然常数 (e) 的定义推出的重要极限。因此最终得到:

[ (\ln x)' = \frac{1}{x} ]

这个证明虽然步骤多一些,但更“原生”,它没有借助 (e^x) 的导数,而是直接落在“对数函数 (1/t) 的极限”上。

4.3 绝对值到底从哪来

很多同学会问:既然上面证明的是 ((\ln x)' = 1/x),为什么不定积分里要写成 (\ln|x|)?

原因是定义域。(y=\frac{1}{x}) 在 (x<0) 的半轴上也是有定义的,但 (\ln x) 在 (x<0) 时没有意义。如果只写 (\ln x + C),就把原函数限制在了 (x>0) 这一半区间上,丢掉了另一半。

为了覆盖 (x<0) 的部分,我们看函数:

[ \ln(-x) ]

对它求导,使用链式法则:

[ \frac{d}{dx} \ln(-x) = \frac{1}{-x} \cdot (-1) = \frac{1}{x} ]

所以 (\ln(-x)) 也是 (\frac{1}{x}) 的一个原函数,只不过它定义在 (x<0) 的区间上。把两种情况合并,就得到了:

[ \ln|x| = \begin{cases} \ln x, & x>0 \ \ln(-x), & x<0 \end{cases} ]

因此:

[ \int \frac{1}{x} dx = \ln|x| + C ]

注意,这里的绝对值不是一个可有可无的装饰。如果不写绝对值,就默认只在 (x>0) 上成立。在 (x=0) 处,原函数没有定义,因为 (1/x) 在该点本身不连续,面积积分在这里发散,不能直接跨过去。

5. 用 Python/SymPy 验证原函数、导数和定积分

数学推导再多,也不如亲手跑一遍代码来得直观。下面我会用 Python 做三类验证:符号求导、数值求导、定积分验证,最后再画个图,让你直观看到 (1/x) 和 (\ln|x|) 的关系。

5.1 环境准备

建议使用 Python 3.8 或更高版本,并安装几个常用科学计算库:

pip install sympy scipy matplotlib numpy

版本不一定要最新,以你当前环境能正常安装为准。下面代码里用到的 API 都是比较稳定的常用接口。

5.2 符号验证

先用 SymPy 验证“对 (\ln|x|) 求导能得到 (1/x)”,同时试试直接对 (1/x) 做不定积分:

import sympy as sp x = sp.symbols('x') F = sp.log(sp.Abs(x)) print("diff(log(abs(x)), x) =", sp.diff(F, x)) print("integrate(1/x, x) =", sp.integrate(1/x, x))

运行这段代码,第一行通常输出1/x。第二行在不同 SymPy 版本下的输出可能略有差异,常见结果会是log(x)

这里需要提醒一个容易忽略的细节:SymPy 默认把符号变量 (x) 当成复数处理,所以在复数域下,它更倾向于给出log(x)这种解析形式。而实数域里的严格写法是 (\log|x|)。因此,不要看到integrate(1/x, x)返回log(x)就觉得“程序写错了”,它和你使用的数学分支有关。对于实数域问题,我们可以在心中补上绝对值,或者干脆用log(abs(x))来做后续验证。

5.3 数值导数验证

我们把“符号求导”再换成“数值求导”,用中心差分格式验证:

import math def F(x): return math.log(abs(x)) h = 1e-7 for a in [0.5, 1.0, 2.0, -0.5, -2.0]: derivative = (F(a + h) - F(a - h)) / (2 * h) print(f"x = {a:>6}: 数值导数 = {derivative:.10f}, 1/x = {1/a:.10f}")

中心差分公式是:

[ F'(a) \approx \frac{F(a+h) - F(a-h)}{2h} ]

只要 (h) 足够小,数值导数和 (\frac{1}{a}) 就会非常接近。特别要注意,当 (a=-0.5) 或 (a=-2) 时,(\ln|x|) 的导数仍然等于 (\frac{1}{a}),这就验证了绝对值写法确实覆盖了负数区间。

5.4 定积分验证

再用 SciPy 的quad计算定积分,和 (\ln|b| - \ln|a|) 对比:

from scipy.integrate import quad import math intervals = [(1, 2), (0.5, 1), (-2, -1)] for a, b in intervals: val, err = quad(lambda x: 1 / x, a, b) exact = math.log(abs(b)) - math.log(abs(a)) print(f"∫_{a}^{b} 1/x dx ≈ {val:.8f}, 精确值 = {exact:.8f}")

这段代码会输出三个区间上的积分,结果和 (\ln|b| - \ln|a|) 保持一致。这里要特别注意:积分区间不能跨过 (x=0),因为 (1/x) 在原点不连续、面积积分发散。如果写quad(lambda x: 1/x, -1, 1),大概率会得到无穷大或警告,这正是数学上“瑕积分”要处理的边界情况。

5.5 图像观察

最后画一个图,把反比例函数和原函数放在同一行对比:

import numpy as np import matplotlib.pyplot as plt x_left = np.linspace(-3, -0.1, 300) x_right = np.linspace(0.1, 3, 300) fig, axes = plt.subplots(1, 2, figsize=(10, 4)) axes[0].plot(x_left, 1 / x_left, 'b', label='y = 1/x') axes[0].plot(x_right, 1 / x_right, 'b') axes[0].set_title('反比例函数') axes[0].axhline(0, color='black', lw=0.8) axes[0].axvline(0, color='black', lw=0.8) axes[0].legend() axes[0].grid(True) axes[1].plot(x_left, np.log(np.abs(x_left)), 'r', label='y = ln|x|') axes[1].plot(x_right, np.log(np.abs(x_right)), 'r') axes[1].set_title('原函数') axes[1].axhline(0, color='black', lw=0.8) axes[1].axvline(0, color='black', lw=0.8) axes[1].legend() axes[1].grid(True) plt.tight_layout() plt.show()

从图像上能看得很清楚:(y=\frac{1}{x}) 在原点处断开,而 (y=\ln|x|) 在 (x>0) 和 (x<0) 两侧分别定义。虽然图像也分成两支,但它的导数确实处处等于对应的 (\frac{1}{x})。这和代数推导是吻合的。

6. 几个连续例子:从反比例函数原函数到对数运算

记住“对数函数的导数是倒数”这个核心规律之后,很多看上去复杂的积分都可以秒推出来。下面几个例子,本质上都是 (1/x) 型积分或它的换元版本。

6.1 常数倍

[ \int \frac{2}{x} dx = 2\ln|x| + C ]

这个没什么好说的,常数因子直接提出来。

6.2 线性换元

[ \int \frac{1}{2x+1} dx ]

这里分母是 (2x+1),分子是 1。如果我们希望把积分变成“分母分之一”,需要凑出分母的导数。(2x+1) 的导数是 2,所以:

[ \int \frac{1}{2x+1} dx = \frac{1}{2} \int \frac{2}{2x+1} dx = \frac{1}{2} \ln|2x+1| + C ]

这种“分子是分母的导数”的模式非常常见。只要乘法常数处理好,结果就是对数函数。

6.3 三角函数有理式

再比如:

[ \int \cot x dx = \int \frac{\cos x}{\sin x} dx ]

分母是 (\sin x),分子是 (\cos x),而 (\cos x) 恰好是 (\sin x) 的导数。所以可以直接写成:

[ \int \cot x dx = \ln|\sin x| + C ]

这里同样带着绝对值,因为 (\sin x) 会变号,而我们希望 (\ln) 的参数保持正数。

这几个例子说明一个通用套路:当被积函数可以写成 (\frac{g'(x)}{g(x)}) 时,积分结果就是 (\ln|g(x)| + C)。用这个视角再看反比例函数,其实这就是 (g(x)=x) 的特例。所以你可以把 (\ln|x|) 看作“分母的导数在分子上”这一类积分的基础模板。

7. 常见误区与易错点

这一节把初学者最容易犯的错误整理成一张表,方便以后排查问题。

问题现象可能原因正确理解处理方式
把 (\int x^{-1} dx) 写成 (\frac{x^0}{0}+C)直接套用幂函数积分公式(n=-1) 时公式失效使用 (\ln|x|+C)
只写 (\ln x + C),丢掉绝对值忽略负半轴定义域(1/x) 在 (x<0) 也有定义在实数域写 (\ln|x|+C)
认为 (\ln|x|) 在 (x=0) 处有定义对对数函数定义域不清晰(\ln|x|) 在 0 处无定义原函数定义域同样排除 0
定积分直接跨 0 计算把反常积分当成普通定积分(1/x) 在原点发散分段处理,或讨论柯西主值
忽视常数项 (C)只写出一个原函数不定积分是一族函数记得 (+C)
认为两个区间共用同一个 (C)默认连续区间上常数一致定义域分两支时 (C) 可以不同严格写法可分 (x>0) 和 (x<0) 两段

其中最后一条,是很多进阶学习者也会忽略的细节。由于 (1/x) 的定义域分成两个不相连的区间,原函数在 (x>0) 和 (x<0) 上可以分别加上不同的常数。比如:

[ F(x) = \begin{cases} \ln x + 1, & x>0 \ \ln(-x) + 5, & x<0 \end{cases} ]

这个函数的导数仍然是 (1/x)。所以 (\int \frac{1}{x} dx = \ln|x| + C) 这种写法,其实在“整个定义域”上并不严谨,它默认了一个全局常数。不过大多数教材和工程计算都采取这种简洁写法,你需要知道它背后隐含了什么,但不必每次都用分段函数折磨自己。

还有一个误区与程序库有关。很多语言里的log(x)只接受正数参数,如果传入负数,会返回NaN或抛出异常。在实际编码时,如果你要处理“实数域上的对数绝对值”,要写成math.log(abs(x))np.log(np.abs(x)),不要直接对负数取对数。

8. 这个结论在算法与工程中的实际应用

你可能会觉得,一个数学公式,在写业务代码时根本用不上。但事实上,这个结论在机器学习、概率统计、数值计算里出现得非常频繁。

最典型的是对数损失函数。逻辑回归里,交叉熵损失函数包含 (\ln p) 项,对参数求导时会出现 (\frac{1}{p}) 这种形式。概率 (p) 必须在 ((0,1)) 范围内,所以那里不需要绝对值符号,但你必须保证概率值永远大于 0。这其实就是在“对数函数的定义域”和“数值稳定性”之间做工程取舍,比如实现时会给 (p) 加一个极小的eps,防止出现log(0)

另一个例子是信息熵。离散熵的定义是:

[ H(X) = -\sum_{i} p_i \ln p_i ]

连续熵里面则会出现积分形式:

[ h(X) = -\int p(x) \ln p(x) dx ]

当某些概率密度函数本身包含 (\frac{1}{x}) 形式的因子时,你会经常遇到 (\int \frac{1}{x} dx = \ln|x|) 的变形。理解原函数结构,能帮你更快判断这个积分是否收敛、是否需要拆区间。

再往深处说,调和级数和 (\ln n) 之间的关系也来自这里。(\sum_{k=1}^n \frac{1}{k}) 的增长速度约等于 (\ln n),这正是因为 (\frac{1}{x}) 的积分是 (\ln x)。所以在做算法复杂度分析时,出现“调和级数复杂度 (O(\log n))”的底层原因,和反比例函数积分为对数函数完全是一回事。

在数值计算里,遇到 (\frac{1}{x}) 型积分时还要警惕奇异点。SciPyquad默认会对被积函数采样,如果区间跨过 0,很容易计算出无穷大或发出积分不收敛的警告。工程上通常会避开奇点、拆分成左右两侧分别积分,或者用更专业的反常积分方法处理。这已经不是单纯套公式的问题,而是要对“原函数在哪里不存在”有清晰的感知。

9. 从这个问题延伸:后续可以继续学什么

弄明白了“为什么反比例函数的原函数是 lnx”,你其实已经打通了一条理解微积分的主线:幂函数、指数函数、对数函数之间通过导数和积分形成了闭环。下一步可以从这个点继续向外延伸。

第一个方向是学习更多“不同类型原函数”的例子。比如:

[ \int \frac{1}{x^2+1} dx = \arctan x + C ]

这里出现的是反三角函数,背后的逻辑和 (\ln|x|) 很相似:当被积函数不能用普通幂函数解决时,新函数就会出现。理解 (1/x) 的对数原函数,就是理解这一整类“原函数扩张”的基础。

第二个方向是复变函数。在实变量下,(\int 1/x dx = \ln|x| + C) 需要分段讨论绝对值;但在复变量下,对数函数 (\log z) 是多值的,绝对值不再是主角。你会在复分析里重新见到这个公式,感受会很不一样。

第三个方向是反常积分和柯西主值。(1/x) 在 (x=0) 处发散,那么 (\int_{-1}^{1} \frac{1}{x} dx) 到底等于多少?如果按对称性“抵消”,有人说等于 0,但严格按黎曼积分的定义,它并不收敛。这种边界问题,在信号处理和概率论中都可能突然冒出来,值得提前了解。

回到最初的问题:不要只记 (\ln|x|+C),而是理解“为什么”。因为这个看似简单的公式,背后连接着极限、导数、积分、定义域、数值稳定性等一系列技术判断。对于经常写代码的开发者来说,这种“从数学到工程”的迁移能力,往往比公式本身更值钱。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 20:29:04

GPU加速大数据:原理、生态与实战全解析

1. 为什么GPU正在成为大数据的下一个胜负手过去十年聊大数据&#xff0c;大家争论最多的是“用Hadoop还是MongoDB”“数据湖能不能取代数据仓库”&#xff0c;本质上都在解决一个问题&#xff1a;如何把越来越大的数据稳定地存下来、查得动。那时候瓶颈在磁盘、网络和分布式系统…

作者头像 李华
网站建设 2026/9/7 20:27:32

Spark与协同过滤小说推荐平台实战:从环境搭建到答辩全攻略

每年三四月份&#xff0c;总有一批计算机专业的学生在毕设和答辩之间反复横跳。如果你拿到的题目是"基于Spark与协同过滤的小说推荐平台"这种&#xff0c;八成已经被三座大山压得喘不过气&#xff1a;第一座是Hadoop生态的环境搭建&#xff0c;第二座是协同过滤算法的…

作者头像 李华
网站建设 2026/9/7 20:25:39

从MapReduce到Spark:大数据性能调优关键路径解析

做大数据的人&#xff0c;只要经历过MapReduce那个年代&#xff0c;大概都忘不了被“跑一批任务等到天亮”支配的感觉。那时候处理几百GB的数据&#xff0c;凑一个稳定跑完的作业都算技术活&#xff0c;更别说什么实时性、交互式查询。后来Spark出现&#xff0c;内存计算的概念…

作者头像 李华
网站建设 2026/9/7 20:25:16

ResNet18、DenseNet121和ResNet50胸片三分类对比

一、为什么要训练三个模型 三个模型解决的是同一个任务&#xff0c;但网络结构不同&#xff1a; ResNet18&#xff1a;层数较浅&#xff0c;残差结构简单&#xff0c;推理速度快&#xff1b;ResNet50&#xff1a;网络更深&#xff0c;使用瓶颈残差块&#xff0c;参数量更大&…

作者头像 李华
网站建设 2026/9/7 20:22:43

conda完全指南:环境管理、包管理与常见报错一次讲清

见字如面。搞 Python 开发这两年&#xff0c;我最常被实习生问的就是“conda 到底怎么用”。那本期就把 conda 的常见指令一次性盘清楚&#xff0c;包括环境管理、包管理、换源、跨平台迁移、以及一堆让你怀疑人生的报错处理。这篇文我尽量用大白话讲透&#xff0c;全程干货&am…

作者头像 李华