来自字符串和字节数组的BigInteger值的区别。

时间:2022-09-25 08:06:39

Can someone please explain the difference between the below two initialisations of BigInteger.

谁能解释一下以下两个BigInteger首字母的区别吗?

Input:

输入:

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));

Output:

输出:

Big Integer1 = ef
Big Integer2 = -11

How can I initialise a BigInteger with the value "EF" from a byte array?

如何从字节数组中初始化带有值“EF”的BigInteger ?

4 个解决方案

#1


5  

From the BigInteger docs

先导入BigInteger文档的

Constructor and Description

构造函数和描述

BigInteger(byte[] val)

BigInteger(byte[]val)

Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger.

将包含BigInteger的二补二进制表示的字节数组转换为BigInteger。

The Two's-complement is the real reason.

“二补”才是真正的原因。

Lets see how...

让我们看看……

(Byte)0xef in binary = 11101111 Now convert that back to Int and you get -17 (base 10) or -11 (base 16).

(字节)二进制= 11101111中的0xef现在将其转换为Int,得到-17(以10为基数)或-11(以16为基数)。

Now take a look at

现在我们来看看

byte[] ba = new byte[] {0, (byte)0xEF};

This has the (Byte)0xef but prepended by 0. Which means this array has 00000000 11101111, which when converted gives the correct result.

这有(字节)0xef,但以0为前缀。这意味着这个数组有00000000 11101111,转换后会得到正确的结果。

Why was the previous case different?

为什么之前的情况不同?

Check out 2's complement rules - SO Answer, Mandatory Wikipedia link

看看2的补充规则——答案,*的链接

Another way of thinking about this

另一种思考方式

0xEF in Decimal = 239

小数点后的0xEF = 239

Range of Byte = -127 to 128

字节的范围= -127到128。

We have Overflow.

我们有溢出。

239 - 128 = 111

239 - 128 = 111

Now count this 111 from back (Numeric data types have this circular behaviour, again due to 2's complement representation).

现在从后面数111(由于2的补语表示,数字数据类型具有这种循环行为)。

For example: 129.toByte = -127

例如:129。toByte = -127

(129 - 128 = 1, count from back the 1st value = -127)

(129 - 128 = 1,第1值= -127)

Shortcut to counting from back if x>128 && x<256 then x.toByte = (x - 128) - 128

如果x>128 & x<256则x,则从后面计数的快捷方式。toByte = (x - 128) - 128。

Here x = 239 so x.toByte = -17

这里x = 239,所以x。toByte = -17

#2


0  

Put a leading zero into the byte[]:

将前导0代入字节[]:

byte[] ba = new byte[] {0, (byte)0xEF};

Ideone demo

Ideone演示

#3


0  

You need to add a zero into the byte[] array:

您需要在字节[]数组中添加一个0:

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));

why?

well the reason is related to the language specification:

原因与语言规范有关:

Decimal literals have a particular property that is not shared by hexadecimal, i.e Decimal literals are all positive [JLS 3.10.1].

十进制文字有一个特殊的属性,十六进制i不共享这个属性。e十进制的文字都是正的[JLS 3.10.1]。

To write a negative decimal constant, you need to use the unary negation operator (-) in combination with a decimal literal.

要写一个负十进制常数,你需要使用一元的否定运算符(-)和一个十进制的文字。

In this way, you can write any int or long value, whether positive or negative, in decimal form, and negative decimal constants are clearly identifiable by the presence of a minus sign.

通过这种方式,您可以将任何int或long值(无论是正数还是负数)写成小数形式,并且负数的十进制常量可以通过负号的存在来明确地识别。

Not so for hexadecimal nor octal literals. They can take on both positive and negative values. Hex and octal literals are negative if their high-order bit is set.

但十六进制和八进制则不是这样。它们可以同时具有正值和负值。如果设置了高阶位,则十六进制和八进制数为负。

So after having said that, 0xFE is actually a negative number...

说了这些之后,0xFE实际上是一个负数。

#4


0  

public BigInteger(byte[] val)

先导入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.

将包含BigInteger的二补二进制表示的字节数组转换为BigInteger。输入数组被假定为大端字节顺序:最重要的字节位于第0元素中。

public BigInteger(String val, int radix)

公共BigInteger(String val, int基数)

Translates the String representation of a BigInteger in the specified radix into a BigInteger. [...]

将指定基数中的BigInteger的字符串表示形式转换为BigInteger。[…]

Source: Oracle Java 7 Docs

来源:Oracle Java 7文档。

Your Initialization from a bytearray does not behave as expected, because 0xEF casted to a bytearray returns {1, 1, 1, 0, 1, 1, 1, 1}.

bytearray的初始化不像预期的那样,因为0xEF被转换为bytearray返回{1,1,1,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1}。

Made to an integer according to the specs mentioned above is done as follows:

按照上述规格制作成整数,如下所示:

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

The two's-compliment causes the highest byte to be substracted, rather than being added. So adding a 0 to the beginningthe byte array should probably fix the problem:

这两个字符会使最高字节被替换,而不是被添加。因此,在开头添加一个0,字节数组应该可以解决这个问题:

byte[] ba = new byte[] {0, (byte)0xEF};

#1


5  

From the BigInteger docs

先导入BigInteger文档的

Constructor and Description

构造函数和描述

BigInteger(byte[] val)

BigInteger(byte[]val)

Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger.

将包含BigInteger的二补二进制表示的字节数组转换为BigInteger。

The Two's-complement is the real reason.

“二补”才是真正的原因。

Lets see how...

让我们看看……

(Byte)0xef in binary = 11101111 Now convert that back to Int and you get -17 (base 10) or -11 (base 16).

(字节)二进制= 11101111中的0xef现在将其转换为Int,得到-17(以10为基数)或-11(以16为基数)。

Now take a look at

现在我们来看看

byte[] ba = new byte[] {0, (byte)0xEF};

This has the (Byte)0xef but prepended by 0. Which means this array has 00000000 11101111, which when converted gives the correct result.

这有(字节)0xef,但以0为前缀。这意味着这个数组有00000000 11101111,转换后会得到正确的结果。

Why was the previous case different?

为什么之前的情况不同?

Check out 2's complement rules - SO Answer, Mandatory Wikipedia link

看看2的补充规则——答案,*的链接

Another way of thinking about this

另一种思考方式

0xEF in Decimal = 239

小数点后的0xEF = 239

Range of Byte = -127 to 128

字节的范围= -127到128。

We have Overflow.

我们有溢出。

239 - 128 = 111

239 - 128 = 111

Now count this 111 from back (Numeric data types have this circular behaviour, again due to 2's complement representation).

现在从后面数111(由于2的补语表示,数字数据类型具有这种循环行为)。

For example: 129.toByte = -127

例如:129。toByte = -127

(129 - 128 = 1, count from back the 1st value = -127)

(129 - 128 = 1,第1值= -127)

Shortcut to counting from back if x>128 && x<256 then x.toByte = (x - 128) - 128

如果x>128 & x<256则x,则从后面计数的快捷方式。toByte = (x - 128) - 128。

Here x = 239 so x.toByte = -17

这里x = 239,所以x。toByte = -17

#2


0  

Put a leading zero into the byte[]:

将前导0代入字节[]:

byte[] ba = new byte[] {0, (byte)0xEF};

Ideone demo

Ideone演示

#3


0  

You need to add a zero into the byte[] array:

您需要在字节[]数组中添加一个0:

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));

why?

well the reason is related to the language specification:

原因与语言规范有关:

Decimal literals have a particular property that is not shared by hexadecimal, i.e Decimal literals are all positive [JLS 3.10.1].

十进制文字有一个特殊的属性,十六进制i不共享这个属性。e十进制的文字都是正的[JLS 3.10.1]。

To write a negative decimal constant, you need to use the unary negation operator (-) in combination with a decimal literal.

要写一个负十进制常数,你需要使用一元的否定运算符(-)和一个十进制的文字。

In this way, you can write any int or long value, whether positive or negative, in decimal form, and negative decimal constants are clearly identifiable by the presence of a minus sign.

通过这种方式,您可以将任何int或long值(无论是正数还是负数)写成小数形式,并且负数的十进制常量可以通过负号的存在来明确地识别。

Not so for hexadecimal nor octal literals. They can take on both positive and negative values. Hex and octal literals are negative if their high-order bit is set.

但十六进制和八进制则不是这样。它们可以同时具有正值和负值。如果设置了高阶位,则十六进制和八进制数为负。

So after having said that, 0xFE is actually a negative number...

说了这些之后,0xFE实际上是一个负数。

#4


0  

public BigInteger(byte[] val)

先导入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.

将包含BigInteger的二补二进制表示的字节数组转换为BigInteger。输入数组被假定为大端字节顺序:最重要的字节位于第0元素中。

public BigInteger(String val, int radix)

公共BigInteger(String val, int基数)

Translates the String representation of a BigInteger in the specified radix into a BigInteger. [...]

将指定基数中的BigInteger的字符串表示形式转换为BigInteger。[…]

Source: Oracle Java 7 Docs

来源:Oracle Java 7文档。

Your Initialization from a bytearray does not behave as expected, because 0xEF casted to a bytearray returns {1, 1, 1, 0, 1, 1, 1, 1}.

bytearray的初始化不像预期的那样,因为0xEF被转换为bytearray返回{1,1,1,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1}。

Made to an integer according to the specs mentioned above is done as follows:

按照上述规格制作成整数,如下所示:

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

The two's-compliment causes the highest byte to be substracted, rather than being added. So adding a 0 to the beginningthe byte array should probably fix the problem:

这两个字符会使最高字节被替换,而不是被添加。因此,在开头添加一个0,字节数组应该可以解决这个问题:

byte[] ba = new byte[] {0, (byte)0xEF};