Python 中的浮点值与记录值
Float versus Logged values in Python
我正在计算单词的相对频率(单词数/单词总数)。这会导致很多非常小的数字(例如 1.2551539760140076e-05)。我已经阅读了在这种情况下使用浮点数的一些问题,例如在这个 article
A float has roughly seven decimal digits of precision ...
有些人建议改用记录值。我要将这些数字相乘并且想知道
- 总的来说,Python 中的七位数规则是什么?
- 在我的例子中,我应该改用对数值吗?
- 如果我不这样做,可能会发生什么不好的事情——只是一个不太准确的值或直接的错误,例如在乘法中?
- 如果是这样,我是否只用 math.log() 转换浮点数 - 我觉得那时信息已经丢失了?
非常感谢任何帮助!
那篇文章讲的是C中的float
类型,是32位的量。 Python 类型 float
是一个 64 位数字,就像 C 的 double
一样,因此可以存储大约 17 个十进制数字(53 个小数位而不是 C 的 float
的 24 个)。虽然对于某些应用程序来说这也可能太低精度,但它比 32 位浮点数要好得多。
此外,因为它是 浮点数 格式,所以像 1.2551539760140076e-05
这样的小数字(实际上并没有那么小)并没有天生的劣势。虽然只能表示大约 17 位小数,但这 17 位不必是小数点后的前 17 位。它们可以左右移动,可以这么说1。事实上,当您将数字表示为一串十进制数字乘以 10 的幂 (e-5
) 时,您使用了 浮点(小数)点 的相同概念。举个极端的例子,1-300可以很好地表示2,10300也可以——只有当这两个数字相遇时,问题才会发生(1e300 + 1e-300 == 1e300
)。
至于对数表示,您将尽早获取所有值的对数,并在对数 space 中执行尽可能多的计算。在您的示例中,您将计算单词的相对频率为 log(word_count) - log(total_words)
,这与 log(word_count / total_words)
相同,但可能更准确。
What bad things could happen if I don't -- just a less accurate value or straight up errors, e.g. in the multiplication?
我不确定区别是什么。数值计算可以具有近乎完美的精度(相对舍入误差在 2-50 或更好的范围内),但不稳定的算法在某些情况下也会给出可笑的糟糕结果。每个单独操作的舍入误差都有相当严格的界限3,但在较长的计算中,它们以令人惊讶的方式相互作用,导致非常大的误差。例如,即使只是对大量浮点数求和也会引入重大错误,尤其是当它们的大小和符号非常不同时。可靠的数值算法的正确分析和设计本身就是一门艺术,我不能在这里公正地对待它,但是由于 IEEE-754 的良好设计,大多数 算法通常锻炼还可以。不要太在意,但也不要忽视。
1 事实上,我们谈论的是 53 binary 位被移动,但这对于这个概念并不重要。存在十进制浮点格式。
2 相对舍入误差小于 2-54,对于任何分母不是幂的分数都会出现两个,包括像 1/3 或 0.1
.
这样平凡的
3对于基本的算术运算,舍入误差应在最后一位为半个单位,即结果必须准确计算,然后正确舍入。对于超越函数,误差很少超过最后一位的一两个单位,但可能更大。
我正在计算单词的相对频率(单词数/单词总数)。这会导致很多非常小的数字(例如 1.2551539760140076e-05)。我已经阅读了在这种情况下使用浮点数的一些问题,例如在这个 article
A float has roughly seven decimal digits of precision ...
有些人建议改用记录值。我要将这些数字相乘并且想知道
- 总的来说,Python 中的七位数规则是什么?
- 在我的例子中,我应该改用对数值吗?
- 如果我不这样做,可能会发生什么不好的事情——只是一个不太准确的值或直接的错误,例如在乘法中?
- 如果是这样,我是否只用 math.log() 转换浮点数 - 我觉得那时信息已经丢失了?
非常感谢任何帮助!
那篇文章讲的是C中的float
类型,是32位的量。 Python 类型 float
是一个 64 位数字,就像 C 的 double
一样,因此可以存储大约 17 个十进制数字(53 个小数位而不是 C 的 float
的 24 个)。虽然对于某些应用程序来说这也可能太低精度,但它比 32 位浮点数要好得多。
此外,因为它是 浮点数 格式,所以像 1.2551539760140076e-05
这样的小数字(实际上并没有那么小)并没有天生的劣势。虽然只能表示大约 17 位小数,但这 17 位不必是小数点后的前 17 位。它们可以左右移动,可以这么说1。事实上,当您将数字表示为一串十进制数字乘以 10 的幂 (e-5
) 时,您使用了 浮点(小数)点 的相同概念。举个极端的例子,1-300可以很好地表示2,10300也可以——只有当这两个数字相遇时,问题才会发生(1e300 + 1e-300 == 1e300
)。
至于对数表示,您将尽早获取所有值的对数,并在对数 space 中执行尽可能多的计算。在您的示例中,您将计算单词的相对频率为 log(word_count) - log(total_words)
,这与 log(word_count / total_words)
相同,但可能更准确。
What bad things could happen if I don't -- just a less accurate value or straight up errors, e.g. in the multiplication?
我不确定区别是什么。数值计算可以具有近乎完美的精度(相对舍入误差在 2-50 或更好的范围内),但不稳定的算法在某些情况下也会给出可笑的糟糕结果。每个单独操作的舍入误差都有相当严格的界限3,但在较长的计算中,它们以令人惊讶的方式相互作用,导致非常大的误差。例如,即使只是对大量浮点数求和也会引入重大错误,尤其是当它们的大小和符号非常不同时。可靠的数值算法的正确分析和设计本身就是一门艺术,我不能在这里公正地对待它,但是由于 IEEE-754 的良好设计,大多数 算法通常锻炼还可以。不要太在意,但也不要忽视。
1 事实上,我们谈论的是 53 binary 位被移动,但这对于这个概念并不重要。存在十进制浮点格式。
2 相对舍入误差小于 2-54,对于任何分母不是幂的分数都会出现两个,包括像 1/3 或 0.1
.
3对于基本的算术运算,舍入误差应在最后一位为半个单位,即结果必须准确计算,然后正确舍入。对于超越函数,误差很少超过最后一位的一两个单位,但可能更大。