为什么不使用二进制补码进行任意精度整数的减法?

Why not use two's compliment for subtraction in arbitrary precision integer?

Java 的 BigInteger class 使用以下代码从较大的数字中减去较小的数字:

    private static int[] subtract(int[] big, int[] little) {
        int bigIndex = big.length;
        int result[] = new int[bigIndex];
        int littleIndex = little.length;
        long difference = 0;

        // Subtract common parts of both numbers
        while (littleIndex > 0) {
            difference = (big[--bigIndex] & LONG_MASK) -
                         (little[--littleIndex] & LONG_MASK) +
                         (difference >> 32);
            result[bigIndex] = (int)difference;
        }

        // Subtract remainder of longer number while borrow propagates
        boolean borrow = (difference >> 32 != 0);
        while (bigIndex > 0 && borrow)
            borrow = ((result[--bigIndex] = big[bigIndex] - 1) == -1);

        // Copy remainder of longer number
        while (bigIndex > 0)
            result[--bigIndex] = big[bigIndex];

        return result;
    }

我的问题是,在 little 上简单地执行 ~x+1 而不更改符号的值并将其添加到 big 不是更直接吗?这会不会特别慢?如果是,为什么?

n 位整数的 2 补码表示实际上是惯例,等于或大于 Math.pow(2,n-1) 的无符号整数值 b 不表示存储的值,而是表示值 b-(Math.pow(2,n-1)+1),这是负数。由于计算机现在执行环绕算术(意思是 a+b 实际上计算 (a+b) % Math.pow(2, n),基本算术在此约定中产生正确的结果。

如果您现在转到 BigIntegers,您希望避免这种情况。您不想要最大整数值 Math.pow(2,n-1)-1,高于该值的数字突然变为负数。而且你不需要包装算术,你想要真正的整数算术。二进制补码表示绑定到可用整数的特定范围。

大整数存储在 "digits" 的字符串中,其中最高有效位以上的数字被称为零。从理论上讲,您可能会找到一些创造性的方式来存储整数,方法是定义最上面存储的所有位都应该等于存储的最上面的位,然后所有负数 -b 都存储为 Infinity-b 或其他东西,但这会使事情在很多方面变得非常复杂。所以使用符号和幅度存储要容易得多,即使它可能需要更多的存储空间。