鉴于如果列表中没有 0,我们可以轻松地在列表中的项目与列表中项目的对数和之间进行转换,例如:
>>> from operator import mul
>>> pn = [0.4, 0.3, 0.2, 0.1]
>>> math.pow(reduce(mul, pn, 1), 1./len(pn))
0.22133638394006433
>>> math.exp(sum(0.25 * math.log(p) for p in pn))
0.22133638394006436
我们应该如何处理列表和 Python 中有 0 的情况(以编程和数学上正确的方式)?
更具体地说,我们应该如何处理以下情况:
>>> pn = [0.4, 0.3, 0, 0]
>>> math.pow(reduce(mul, pn, 1), 1./len(pn))
0.0
>>> math.exp(sum(1./len(pn) * math.log(p) for p in pn))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
ValueError: math domain error
返回 0 真的是处理这个问题的正确方法吗?什么是优雅的解决方案,我们考虑列表中的 0 但不是以 0 结尾?
因为它是某种几何平均值(列表的乘积)并且当我们返回 0 时它并不是完全有用,因为列表中只有一个 0。
从 Math Stackexchange 溢出: https://math.stackexchange.com/questions/1727497/resolving-zeros-in-product-of-items-in-list , 没有数学家的回答,也许 python/code Jedis 在解决这个问题上有更好的想法。
最佳答案
TL;DR:是的,返回 0 是唯一正确的方法。 (但请参阅结论。)
数学背景
在实数分析中(即不适用于复数),当考虑对数时,我们传统上假设 log
的定义域是正数。我们有身份:
x = exp(log(x)), for x>0.
它可以自然地扩展为 x=0
,因为右侧表达式的极限在 x->0+
处明确定义且等于 0。此外,设置 log(0)=-inf
和 exp(-inf)=0
是合法的(同样:仅适用于实数,而非复数)。形式上,我们扩展实数集,添加两个元素 -inf
、+inf
并定义一致算法等。(为了我们的目的,我们需要有 inf + x = inf
, x * inf = inf
对于真实的 x, inf + inf = inf
等)
另一个身份 x = log(exp(x))
不那么麻烦并且适用于所有实数(甚至 x=-inf
或 + inf
).
几何平均数
可以为非负数(可能等于零)定义几何平均值。对于两个数字a
,b
(它自然地泛化到更多数字,所以我将只使用两个),它是
gm(a,b) = sqrt(a*b), for a,b >= 0.
当然,gm(0,b)=0
。记录下来,我们得到:
log(gm(a,b)) = (log(a) + log(b))/2
如果 a
或 b
为零,则定义明确。 (我们可以插入 log(0) = -inf
,由于我们之前定义的扩展算法,恒等式仍然成立。)
解释
毫不奇怪,几何平均数的概念源自几何学,最初(在古希腊)用于严格的正数。
假设,我们有一个边长为a
和b
的矩形。找一个面积等于长方形面积的正方形。很容易看出,正方形的边是a
和b
的几何平均数。
现在,如果我们采用 a = 0
,那么我们实际上并没有矩形,这种几何解释就失效了。其他解释也会出现类似的问题。例如,我们可以通过考虑退化的矩形和正方形来减轻它,但这可能并不总是一种合理的方法。
结论
这取决于用户(数学家、工程师、程序员)如何理解几何平均值为零的含义。如果它导致结果解释出现严重问题或破坏计算机程序,那么首先,几何平均数的选择可能作为数学模型是不合理的。
python
正如其他答案中已经提到的,python 实现了无穷大。它在执行 np.exp(np.log(0))
但操作结果正确时引发运行时警告(被零除)。
关于python - 解决列表中项目的产品中的零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36416018/