记录BigInteger的两个构造方法
---------------------------------------------------------------------------------------------------------------------------------------
如果着急,可直接拉到最后看结论。如果结论看不懂,可以从头慢慢看起,也查阅别人的相关文档
--------------- 以下全为个人理解,知识有限,理解可能有错,谨慎借鉴 -------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
构造方法: BigInteger(byte[] val)
构造方法: BigInteger(byte[] val) |
下面代码的注释,分别列出来了输出结果(结果:),输出结果的二进制(BIN:),和字节数组的每个自己对应的二进制,并进行比较,以及列出了输出结果的原码,以及toString后的16进制字符串:
//一个字节8位
System.out.println(new BigInteger(new byte[]{11,22}).toString(16)); //结果b16
System.out.println(new BigInteger(new byte[]{11,22})); //结果2838
//BIN(2838): 0000 1011 0001 0110
//BIN(11): 0000 1011
//BIN(22): 0001 0110
//HEX: 0 b 1 6
//2838原码: 0000 1011 0001 0110
System.out.println(new BigInteger(new byte[]{-11,22}).toString(16)); //结果-aea
System.out.println(new BigInteger(new byte[]{-11,22})); //结果-2794
//BIN(-2794): 1111 0101 0001 0110
//BIN(-11): 1111 0101
//BIN(22): 0001 0110
//HEX: -0 a e a
//-2794原码: 1000 1010 1110 1010
System.out.println(new BigInteger(new byte[]{-11,-22}).toString(16)); //结果-a16
System.out.println(new BigInteger(new byte[]{-11,-22}));//结果-2582
//BIN(-2582): 1111 0101 1110 1010
//BIN(-11): 1111 0101
//BIN(-22): 1110 1010
//HEX: -0 a 1 6
//-2582原码: 1000 1010 0001 0110
System.out.println(new BigInteger(new byte[]{11,-22}).toString(16)); //结果bea
System.out.println(new BigInteger(new byte[]{11,-22})); //结果3050
//BIN(3050): 0000 1011 1110 1010
//BIN(11): 0000 1011
//BIN(-22): 1110 1010
//HEX: 0 b e a
//-3050原码: 0000 1011 1110 1010
System.out.println(new BigInteger(new byte[]{-22,11}).toString(16)); //结果-15f5
System.out.println(new BigInteger(new byte[]{-22,11})); //结果-5621
//BIN(-5621): 1110 1010 0000 1011
//BIN(-22): 1110 1010
//BIN(11): 0000 1011
//HEX: -1 5 f 5
//-5621原码: 1001 0101 1111 0101
先说一下此构造方法是怎么得到结果的:
- 将字节数组遍历,得到每个字节的计算机二进制存储值(正数为原码,负数为补码,一个字节8位)
- 将得到的所有字节的二进制进行拼接,形成单个新的二进制
打印结果可以得出结论:
- 构造方法参数字节数组0索引位置(第一位)的字节为负,则构造生成的新的单个二进制为负(有符号数二进制最高位为1)
- 反之,构造方法参数字节数组0索引位置(第一位)的字节为正,则构造生成的新的单个二进制为正(有符号数二进制最高位为0)
BigInteger 中 toString(进制)方法
通过打印结果可以得出(转16进制字符串)结论:
-
BigInteger包装的是正数,是以原码存储,则将该数二进制直接求出16进制字符串
-
BigInteger包装的是负数,是以补码存储,则先求出原码,然后求出16进制字符串(补码的补码就是原码,或者根据求补码的运算逆运算回去得到原码)
-
转为16进制时,最高位符号位0转为 +(可省略),最高位符号位1转为 - ,其余位转为对应16进制
思考: 二进制转16进制,每四位转为一个16进制位,此时最高位一位被占位符号位,所以这里在想, 通过BigInteger包装的数调用 toString(int radix)转为16进制后,由于最高位被占位,所以第一位16进制位的数只能表示0000-0111, 也就是0H--6H,合理思考,还没验证!
构造方法: BigInteger(int signum, byte[] magnitude)
BigInteger(int signum, byte[] magnitude) |
System.out.println(new BigInteger(new byte[]{-11})); //结果 -11
//BIN(-11): 1111 0101
//BIN(-11): 1111 0101
System.out.println(new BigInteger(1, new byte[]{-11})); //结果 245
//BIN(245): 1111 0101
//BIN(-11): 1111 0101
System.out.println(new BigInteger(1, new byte[]{11, 22})); //结果 2838
//BIN(2838): 0000 1011 0001 0110
//BIN(11): 0000 1011
//BIN(22): 0001 0110
System.out.println(new BigInteger(1, new byte[]{-11, 22}));//结果 62742
//BIN(62742): 1111 0101 0001 0110
//BIN(-11): 1111 0101
//BIN(22): 0001 0110
System.out.println(new BigInteger(1, new byte[]{11, -22}));//结果 3050
//BIN(3050): 0000 1011 1110 1010
//BIN(11): 0000 1011
//BIN(-22): 1110 1010
System.out.println(new BigInteger(1, new byte[]{-11, -22}));//结果 62954
//BIN(62954): 1111 0101 1110 1010
//BIN(-11): 1111 0101
//BIN(-22): 1110 1010
System.out.println(new BigInteger(1, new byte[]{-11, -22,-33,-44}));//结果 4125810644
//BIN(62954): 1111 0101 1110 1010 1101 1111 1101 0100
//BIN(-11): 1111 0101
//BIN(-22): 1110 1010
//BIN(-33): 1101 1111
//BIN(-44): 1101 0100
先说一下此构造方法是怎么得到结果的:
- 将字节数组遍历,得到每个字节的计算机二进制存储值(正数为原码,负数为补码,一个字节8位)
- 将得到的所有字节的二进制进行拼接,形成单个新的二进制
- 第一个参数int signum 如果是 1,则代表BigInteger包装的数计算机存储的二进制为正
- 第一个参数int signum 如果是 0,则代表BigInteger包装的数为0
- 第一个参数Int signum 如果是 -1,则代表BigInteger包装的数计算机存储的二进制为负
什么意思?
意思是:
拼接形成一串二进制,这个二进制最高位有可能位0,1。
此时,如果第一个参数是1,那么无论这个二进制最高位为0,还是1,这串二进制都代表一个正数的二进制。也就是说当这串二进制最高位为0(例:0101 0001,这串二进制为原码)代表正数;当这串二进制最高位为1(例:1001 0001,这串二进制为补码),会将这串二进制作为原码来处理。
我们来看下上面代码中前行代码的比较:
System.out.println(new BigInteger(new byte[]{-11})); //结果 -11
//BIN(-11): 1111 0101
//BIN(-11): 1111 0101
System.out.println(new BigInteger(1, new byte[]{-11})); //结果 245
//BIN(245): 1111 0101
//BIN(-11): 1111 0101
- 第一行打印结果为-11,第二行打印结果为245,但是他们的字节数组参数都为{-11},而-11的二进制在计算机中为补码1111 0101。
- 第一行的构造方法中,此时1111 0101这串二进制是作为补码封装到了Biginteger中,所以打印时,会根据补码来计算出原数为-11打印出来。
- 第二行的构造方法中,此时1111 0101这串二进制是作为原码封装到了BigInteger中,所以打印时,直接将1111 0101作为原码打印出其值。
如果第一个参数为0,那么字节数组拼接的结果只能为0,别的结果会报错,如下代码
// System.out.println(new BigInteger(0, new byte[]{-11, -22}));//结果 java.lang.NumberFormatException: signum-magnitude mismatch
// System.out.println(new BigInteger(0, new byte[]{-11})); //结果 java.lang.NumberFormatException: signum-magnitude mismatch
System.out.println(new BigInteger(0, new byte[]{0,0})); //结果 0
System.out.println(new BigInteger(0, new byte[]{0})); //结果 0
System.out.println(new BigInteger(0, new byte[]{})); //结果 0
如果第一个参数为-1,那么无论这个二进制最高位为0,还是1,这串二进制都代表一个正数的二进制。然后计算出这串二进制的补码,将计算出的补码作为补码封装进BigInteger。大致理解为,将字节数组遍历得到每个字节二进制存储值(正为原码,负为补码)然后拼接,得到单个二进制,将这个二进制作为原码求其补码,然后封装到BigInteger中。
再表象点理解,第一个参数为-1的时候,得到的结果就是将第一个参数为1的结果取反。
System.out.println(new BigInteger(-1, new byte[]{11})); //结果 -11
System.out.println(new BigInteger(-1, new byte[]{-11})); //结果 -245
System.out.println(new BigInteger(-1, new byte[]{11, 22})); //结果 -2838
System.out.println(new BigInteger(-1, new byte[]{-11, 22})); //结果 -62742
System.out.println(new BigInteger(-1, new byte[]{11, -22})); //结果 -3050
System.out.println(new BigInteger(-1, new byte[]{-11, -22})); //结果 -62954
|
|
|
|
说这么多,有点罗里吧嗦,不是初衷,本来只想简单记录下这两个构造方法到底怎么用的。那么稍微简单总结下:
BigInteger(byte[] val):
此构造方法传入一个字节数组,会将此字节数组遍历,得到每个字节的二进制(正为原码,负为补码),然后将得到的二进制拼接为一个长的二进制,并封装进BigInteger中。如果此字节数组第一个元素为负,则新拼接的二进制为补码,也就是BigInteger中封装了一个负数。如果此字节数组第一个元素为正,则新拼接的二进制为原码,也就是BigInteger中封装了一个正数。
BigInteger(int signum, byte[] magnitude):
次构造方法传入两个参数,参数一signum代表封装的结果为正,0, 负,相当于标志位;
参数二 magnitude字节数组,代表封装的数值大小。
此构造方法,将传入的字节数组遍历,得到其二进制存储值(正数为原码,负数为补码),然后按顺序拼接成新的二进制串,如果signum为1,则将新拼接成的二进制串(无论最高为位为0或者1)都当做原码来处理;
如果signum为0,则字节数组遍历拼接后的二进制结果必须为0;
如果signum为-1,则将新拼接成的二进制串求出signum为1的值,然后给结果前加个负号“-”。
toString(int radix):
此方法传递一个参数radix,radix意为基数,也就是进制中的基数。N进制的基数就是N。此方法返回一个radix进制的字符串。通俗的讲,就是BigInteger bigInteger = new BigInteger(new byte[]{11,22})这个对象,
bigInteger.toString(N进制)调用方法后,将bigInteger所包装的数转为N进制值的字符串返回。
此方法有个重载放法 **toString()**无参,其默然转为10进制值的字符串表示形式。
---------------------------------------------------------------------------------------------------------------------------------------
------------------------- 以上为个人理解,仅供参考,如有问题欢迎指正 ---------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
来源:CSDN
作者:君心今何在
链接:https://blog.csdn.net/qq_32451661/article/details/103429570