Python 的十进制(以及其他精确的十进制库)是如何实现的?为什么它们比内置的浮点计算慢?

Ken*_*Ken 1 python floating-point decimal

我一直在阅读浮点指南,试图澄清有关浮点数的一些观点,我假设Python的十进制库是链接页面上提到的“有限精度十进制”的实现。

它提到“有限精度十进制”“与 IEEE 754 二进制浮点基本相同,只是指数被解释为基数 10。因此,不会出现意外的舍入错误。而且,这种格式相对紧凑且快速,但通常比二进制格式慢。”

Python十进制的实现方式是一样的吗?如果除了指数解释不同之外,表示形式中的其他所有内容都相同,那么为什么它会更慢,并且为什么这种表示形式并不总是优于 IEEE 754 实现?最后,为什么使用指数作为底数 10 可以防止意外的舍入错误?

谢谢!

Nic*_*ell 7

它提到“有限精度十进制”[...]Python 十进制是否以相同的方式实现?

不,Python 的 Decimal 在内部使用以 10 为底的指数以及任意大的整数。由于整数的大小是无限的,因此潜在的精度也是无限的。

为什么 [Python 的 Decimal] 较慢

这有几个原因。首先,将两个不同指数的 Decimal 值相加需要乘以十,而在使用二进制的计算机上乘以十比乘以二更昂贵。其次,进行精确计算比进行近似计算需要更多的精度。第三,IEEE754 浮点具有硬件加速,因为它是一种常见的操作。

为什么这种表示形式并不总是优于 IEEE 754 实现?

速度是一个特点,并不是所有的计算都能从精确完成中受益。不精确计算的使用比您想象的更广泛。例如,Excel在内部使用浮点数。然而,它拥有数亿用户,因此显然仅使用浮点就可以走得很远。

最后,为什么使用指数作为底数 10 可以防止意外的舍入错误?

这句话的关键词是“出乎意料”。如果您得知以 10 为基数的数字系统无法在不进行四舍五入的情况下表示数字 1/3,您不会感到惊讶。我们理解并且可以接受无法完美准确地表示 1/3、1/7 和 1/9。但人们对于不能准确表示1/5的计算机系统的接受度要低得多。

如果你试图用二进制表示 0.2,你会得到 0.0011(0011),其中 0011 部分会永远重复。浮点数没有无限位数,因此它会四舍五入 53 位(假设双精度)后的所有内容并对其进行近似。

这并不是说 Decimal 完全准确。有很多情况需要强制舍入。例如,如果您取二的平方根,那么这是一个无理数,并且不能表示为精确的小数。

例子:

>>> Decimal(2).sqrt()
Decimal('1.414213562373095048801688724')
>>> Decimal(2).sqrt() ** 2
Decimal('1.999999999999999999999999999')
Run Code Online (Sandbox Code Playgroud)

小数是一种数学计算方法,它与用铅笔和纸计算得到的答案一致。为此,它会权衡速度和内存使用。