为什么 BigInteger 实现使用符号数值而不是二进制补码?

ech*_*ata 9 math binary biginteger arbitrary-precision data-structures

任意精度有符号整数几乎总是使用符号数值表示来实现:

对符号数值的明显偏好与固定宽度有符号整数类型中对二进制补码的近乎普遍的偏好形成鲜明对比。问题是,为什么符号数值对于 BigIntegers 来说如此明显是首选?(如果您不同意前提,我欢迎反例。)

请注意,BigInteger API 通常为重要的位运算指定“如同二进制补码”语义(例如JavaPython )。这提供了与这些操作的通常含义的一致性。这并不规定实际的内部表示(仅是实现细节),但如果其他条件相同,它应该是支持在内部使用二进制补码的一点。

浮点数使用符号数值,与使用二进制补码的整数不同。不过,浮点并不是真正的指导先例,因为浮点运算的行为和算法与整数运算有很大不同。Bignum 更像整数而不是浮点数。

我们知道“教科书”上为什么补码在数学上起作用以及为什么它有优点的原因。在我看来,这些原因同样适用于整数和大整数。这在多大程度上是真的?

当然,硬件固定精度整数和软件任意精度整数的设计约束之间存在巨大差异。从这个意义上说,看到设计师在这些不同的领域做出不同的权衡一点也不奇怪。那么,应用于任意精度整数时,符号-数值和补码之间的权衡是什么?例如,这可能涉及某些重要算法的性能或简单性。

我希望您的回答能够阐明 BigInteger 算术的设计注意事项,并帮助我从新的角度重新审视我对补码的了解。

(需要明确的是:当我说任意精度整数的二进制补码时,我的意思是使用单词数组的表示,其位模式放在一起时是所需数字的二进制补码表示 - 也许还有额外的要求没有“不必要的前导 0”(对于非负数)或“不必要的前导 1”(对于负数)。)

rcg*_*ldr 6

对于相同长度的数字,二进制补码使加法和减法变得更简单,但使乘法和除法变得更复杂。对于硬件实现来说,可能会有时间损失,但并非总是如此。查看 X86“Ivy Bridge”指令表,唯一需要更多时间进行补码的情况是 128 位有符号被除数除以 64 位有符号除数。所以这主要是基于软件的数学的问题。

大整数库可能会使用更复杂但更快的大数表示。以下是一些示例文章的链接:

https://en.wikipedia.org/wiki/Arbitrary- precision_arithmetic

https://cp-algorithms.com/algebra/big-integer.html

http://www.apfloat.org/ntt.html

对于相当大的数字,更复杂的方法通常更快,对于中等大小的数字,更简单的实现会更快。