来自字符串和字节数组的 BigInteger 值的差异
Difference in BigInteger values from a String and a byte array
谁能解释一下下面两个 BigInteger 初始化之间的区别。
输入:
BigInteger bi1 = new BigInteger("EF", 16);
byte[] ba = new byte[] {(byte)0xEF};
BigInteger bi2 = new BigInteger(ba);
Log.d("BIGINTEGER", "Big Integer1 = " + bi1.toString(16));
Log.d("BIGINTEGER", "Big Integer2 = " + bi2.toString(16));
输出:
Big Integer1 = ef
Big Integer2 = -11
如何使用字节数组中的值 "EF" 初始化 BigInteger?
在 byte[]
:
中输入前导零
byte[] ba = new byte[] {0, (byte)0xEF};
public BigInteger(byte[] val)
Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger. The input array is assumed to be in big-endian byte-order: the most significant byte is in the zeroth element.
public BigInteger(String val,
int radix)
Translates the String representation of a BigInteger in the specified radix into a BigInteger. [...]
Source: Oracle Java 7 Docs
您从字节数组进行的初始化未按预期运行,因为 0xEF 转换为字节数组 returns {1, 1, 1, 0, 1, 1, 1, 1}。
根据上述规格做成整数如下:
1*2^0 + 1*2^1 + 1*2^2 + 1*2^3 + 0*2^4 + 1*2^5 + 1*2^6 - 1*2^7 = -17 = -0x11
补码导致最高字节被减去,而不是被添加。所以在字节数组的开头添加一个 0 应该可以解决问题:
byte[] ba = new byte[] {0, (byte)0xEF};
您需要在 byte[]
数组中添加一个零:
byte[] myByteArray = new byte[] {0, (byte)0xEF};
BigInteger bi2 = new BigInteger(ba);
Log.d("BIGINTEGER", "Big Integer1 = " + bi1.toString(16));
Log.d("BIGINTEGER", "Big Integer2 = " + bi2.toString(16));
为什么?
嗯,原因与语言规范有关:
十进制 文字有一个特殊的 属性 不被 十六进制 共享,即十进制文字都是正数 [JLS 3.10.1].
要写负十进制常量,需要结合使用一元求反运算符(-)和十进制字面量。
这样,你可以写入任何int或long值,无论是正数
或负数,十进制形式,负十进制常量可以通过减号清楚地识别。
十六进制或八进制文字并非如此。
它们可以取正值和负值。十六进制和八进制文字是
如果设置了高位,则为负。
所以说了之后,0xFE其实是一个负数...
Constructor and Description
BigInteger(byte[] val)
Translates a byte array containing the two's-complement binary
representation of a BigInteger into a BigInteger.
补码才是真正的原因。
让我们看看如何...
(Byte)0xef
二进制 = 11101111
现在将其转换回 Int 并得到 -17(基数 10)或 -11(基数 16)。
现在看看
byte[] ba = new byte[] {0, (byte)0xEF};
这有 (Byte)0xef
但前面有 0。这意味着这个数组有 00000000 11101111,转换后会给出正确的结果。
为什么之前的案例不同?
查看 2 的补码规则 - SO Answer, Mandatory Wikipedia link
另一种思考方式
十进制的 0xEF = 239
字节范围 = -127 到 128
我们有溢出。
239 - 128 = 111
现在从后面数这个 111(数字数据类型具有这种循环行为,同样是由于 2 的补码表示)。
例如:129.toByte = -127
(129 - 128 = 1, 从后面数第一个值 = -127)
倒数的快捷方式if x>128 && x<256 then x.toByte = (x - 128) - 128
这里 x = 239 所以 x.toByte = -17
谁能解释一下下面两个 BigInteger 初始化之间的区别。
输入:
BigInteger bi1 = new BigInteger("EF", 16);
byte[] ba = new byte[] {(byte)0xEF};
BigInteger bi2 = new BigInteger(ba);
Log.d("BIGINTEGER", "Big Integer1 = " + bi1.toString(16));
Log.d("BIGINTEGER", "Big Integer2 = " + bi2.toString(16));
输出:
Big Integer1 = ef
Big Integer2 = -11
如何使用字节数组中的值 "EF" 初始化 BigInteger?
在 byte[]
:
byte[] ba = new byte[] {0, (byte)0xEF};
public BigInteger(byte[] val)
Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger. The input array is assumed to be in big-endian byte-order: the most significant byte is in the zeroth element.
public BigInteger(String val, int radix)
Translates the String representation of a BigInteger in the specified radix into a BigInteger. [...]
Source: Oracle Java 7 Docs
您从字节数组进行的初始化未按预期运行,因为 0xEF 转换为字节数组 returns {1, 1, 1, 0, 1, 1, 1, 1}。
根据上述规格做成整数如下:
1*2^0 + 1*2^1 + 1*2^2 + 1*2^3 + 0*2^4 + 1*2^5 + 1*2^6 - 1*2^7 = -17 = -0x11
补码导致最高字节被减去,而不是被添加。所以在字节数组的开头添加一个 0 应该可以解决问题:
byte[] ba = new byte[] {0, (byte)0xEF};
您需要在 byte[]
数组中添加一个零:
byte[] myByteArray = new byte[] {0, (byte)0xEF};
BigInteger bi2 = new BigInteger(ba);
Log.d("BIGINTEGER", "Big Integer1 = " + bi1.toString(16));
Log.d("BIGINTEGER", "Big Integer2 = " + bi2.toString(16));
为什么?
嗯,原因与语言规范有关:
十进制 文字有一个特殊的 属性 不被 十六进制 共享,即十进制文字都是正数 [JLS 3.10.1].
要写负十进制常量,需要结合使用一元求反运算符(-)和十进制字面量。
这样,你可以写入任何int或long值,无论是正数 或负数,十进制形式,负十进制常量可以通过减号清楚地识别。
十六进制或八进制文字并非如此。 它们可以取正值和负值。十六进制和八进制文字是 如果设置了高位,则为负。
所以说了之后,0xFE其实是一个负数...
Constructor and Description
BigInteger(byte[] val)
Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger.
补码才是真正的原因。
让我们看看如何...
(Byte)0xef
二进制 = 11101111
现在将其转换回 Int 并得到 -17(基数 10)或 -11(基数 16)。
现在看看
byte[] ba = new byte[] {0, (byte)0xEF};
这有 (Byte)0xef
但前面有 0。这意味着这个数组有 00000000 11101111,转换后会给出正确的结果。
为什么之前的案例不同?
查看 2 的补码规则 - SO Answer, Mandatory Wikipedia link
另一种思考方式
十进制的 0xEF = 239
字节范围 = -127 到 128
我们有溢出。
239 - 128 = 111
现在从后面数这个 111(数字数据类型具有这种循环行为,同样是由于 2 的补码表示)。
例如:129.toByte = -127
(129 - 128 = 1, 从后面数第一个值 = -127)
倒数的快捷方式if x>128 && x<256 then x.toByte = (x - 128) - 128
这里 x = 239 所以 x.toByte = -17