Java 的 BigInteger 符号幅度如何工作

Posted

技术标签:

【中文标题】Java 的 BigInteger 符号幅度如何工作【英文标题】:How Java's BigInteger sign-magnitude works 【发布时间】:2017-03-14 21:53:31 【问题描述】:

考虑以下代码:

int i = 1;
System.out.println("1 binary: " + Long.toBinaryString(i));
long ri = Long.reverse(i);
System.out.println("1 reverse bit decimal: " + ri);
System.out.println("1 reverse bit binary: "+ Long.toBinaryString(ri));
BigInteger bil = new BigInteger(1, Longs.toByteArray(ri));
System.out.println("1 Sign-Magnitude BigInteger toString: " + bil.toString());

输出是:

1 binary: 1
1 reverse bit decimal: -9223372036854775808
1 reverse bit binary: 1000000000000000000000000000000000000000000000000000000000000000
1 Sign-Magnitude BigInteger toString: 9223372036854775808

谁能帮忙解释为什么“1 Sign-Magnitude BigInteger toString:”的值为9223372036854775808 (2^63)?

【问题讨论】:

请阅读关于一个补码、二进制补码(Java 用于 int 和 long 等简单类型)以及 BigInteger 使用的符号幅度。您似乎混淆了 revertinginvertingnegating。在二进制补码中,取反意味着取反和加一。在一个补码中,取反和取反是相同的。在符号幅度中,取反意味着翻转符号位。但是这些都没有revert(即将最低位变为最高位等) 【参考方案1】:

要获得一个值的符号大小,您只需将其绝对值作为大小,并在单独的位(或字节)中记住符号。

722 的符号幅度表示很简单:

sign = 0
magnitude = 722

-722 的符号大小很简单:

sign = 1
magnitude = 722

这也是BigInteger 使用的。

您的代码反转一个值,这意味着,例如,8 位值 00000001 (1) 更改为 10000000(128 或 2^7)。这与 inverting 不同,后者变成例如00000001 (1) 转换为 11111110 (254)。这就是补码的作用。通常使用的二的补码00000001 (1) 否定为11111111 (255,即256 - 1)。你应该阅读two's complement,这需要一些了解。然而,符号大小很容易理解(但并不总是很实用——有符号和无符号的加减法是不同的,等等——这就是大多数处理器使用二进制补码的原因)

再说一遍:符号幅度的工作原理是这样的:

sign = (n < 0)
magnitude = abs(n)

【讨论】:

以上是关于Java 的 BigInteger 符号幅度如何工作的主要内容,如果未能解决你的问题,请参考以下文章

Java中的大数处理类BigInteger和BigDecimar浅析

Java 大数类BigInteger和BigDecimal的基本函数

byte[] 到无符号 BigInteger?

店铺业务场景分析BigDecimal是Java提供的一个不变的任意精度的有符号十进制数对象。它提供了四个构造器,有两个是用BigInteger构造接口怎么使用的重载与重写的区别?分别是什么?

如何在不使用 java.math.BigInteger 的情况下在 Java 中处理非常大的数字

如何在 Java 中将语言环境格式的数字转换为 BigInteger?