记录BigInteger的两个构造方法

谁都会走 提交于 2019-12-09 18:26:09

---------------------------------------------------------------------------------------------------------------------------------------
如果着急,可直接拉到最后看结论。如果结论看不懂,可以从头慢慢看起,也查阅别人的相关文档
--------------- 以下全为个人理解,知识有限,理解可能有错,谨慎借鉴 -------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------

构造方法: 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进制值的字符串表示形式。
---------------------------------------------------------------------------------------------------------------------------------------
------------------------- 以上为个人理解,仅供参考,如有问题欢迎指正 ---------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!