如何处理浮点数,当数字变得非常小以至于变成零时该怎么办?

4

我刚刚修复了以下代码中的一个有趣的错误,但我不确定我采取的方法是最好的:

p = 1
probabilities = [ ... ] # a (possibly) long list of numbers between 0 and 1
for wp in probabilities:

  if (wp > 0):
    p *= wp

# Take the natural log, this crashes when 'probabilites' is long enough that p ends up
# being zero
try:
    result = math.log(p)

由于结果不需要精确,我通过保留最小的非零值来解决这个问题,如果 p 变为 0,就使用该值。

p = 1
probabilities = [ ... ] # a long list of numbers between 0 and 1
for wp in probabilities:

  if (wp > 0):
    old_p = p
    p *= wp
    if p == 0:
      # we've gotten so small, its just 0, so go back to the smallest
      # non-zero we had
      p = old_p
      break

# Take the natural log, this crashes when 'probabilites' is long enough that p ends up
# being zero
try:
    result = math.log(p)

这种方法可行,但对我来说有点笨拙。我不经常进行这种数值编程,并且不确定这是否是人们使用的修复方式,或者是否有更好的选择。

1个回答

9

既然 math.log(a * b) 等于 math.log(a) + math.log(b),为什么不对 probabilities 数组中的所有成员取对数并相加呢?

这样可以避免 p 变得太小而下溢的问题。

编辑:这是 numpy 版本,对于大数据集来说更简洁、更快:

import numpy
prob = numpy.array([0.1, 0.213, 0.001, 0.98 ... ])
result = sum(numpy.log(prob))

太棒了!我知道我必须脱下程序员的帽子,戴上数学家的帽子才能解决这个问题 :-) - Tristan Havelick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接