【Java】工具篇(1):BigInteger类的使用和总结

大家好,我是皮皮猫吖。

每文一言:希望你活得尽兴,而不是过得庆幸。


本篇文章:

有些算法题中,会使用到大整数加法,在学习C/C++的时候,就要手写大整数算法。但是,Java为我们提供了支持大整数加减法的类BigInteger,它可以帮助我们很好的解决大整数加减法的问题。

在学习Java的时候,我只是粗略的学习了下BigInteger类。现在在做一些算法题目,涉及到了一些大整数加减法的问题,重新学习了下BigInteger这个类。写下这篇文章,作为学习BigInteger的总结。

正文如下:

一、创建BigInteger类型数据

1)nextBigInteger()、构造方法方式
① nextBigInteger方式创建BigInteger类型的数据
② new BigInteger(String val):方式创建BigInteger类型的数据
③ new BigInteger(String val,int radix):将radix进制的val数据转化为十进制的BigInteger类型的数据
    //创建BigInteger类型的数据
    @Test
    public void test2(){
        Scanner scanner = new Scanner(System.in);
        //1.创建BigInteger类型的数据
//        BigInteger data1 = scanner.nextBigInteger();
//        System.out.println(data1);
        //2.构造方法方式创建BigInteger类型的数据
        //  BigInteger(String val):将BigInteger的十进制字符串表示形式转换为BigInteger。
        BigInteger data2 = new BigInteger("123");
        System.out.println(data2);
        //3.构造方式创建BigInteger类型的数据
        //  BigInteger(String val, int radix):将指定基数中的BigInteger的String表示形式转换为BigInteger。
        //  radix进制的数据为val,将其转换为十进制类型的BigInteger类型的数据
        BigInteger data3 = new BigInteger("111",2);
        System.out.println(data3);
    }

二、BigInteger常用的一些基本运算方法:加、减、乘、除、取余、取模、绝对值、相反数、n次方等

① 加法:BigInteger add(BigInteger val):

返回值为 (this + val)

② 减法:BigInteger subtract(BigInteger val)

返回值为 (this - val)

③ 乘法:BigInteger multiply(BigInteger val)

返回值为 (this * val)

④ 除法:BigInteger divide(BigInteger val)

返回值为 (this / val)

⑤ 取模:BigInteger mod(BigInteger m)

返回值为 (this mod m )

⑥ 相反数:BigInteger negate()

返回值为 (-this) 。

⑦ exponent次方:BigInteger pow(int exponent)

返回值为 (this^exponent)的BigInteger

⑧ 绝对值:BigInteger abs()

返回一个BigInteger,它的值是此BigInteger的绝对值

⑨取余: BigInteger remainder(BigInteger val)

返回值为 (this % val)

上述方法的返回值都是返回BigInteger类型

 //BigInteger相关的运算方法
    @Test
    public void test3(){
        BigInteger data1 = new BigInteger("12");
        BigInteger data2 = new BigInteger("7");
        //中间变量
        BigInteger temp;
        //1.加法
        temp = data1.add(data2);
        System.out.println(temp);//19

        //2.减法:
        temp = data1.subtract(data2);
        System.out.println(temp);//5

        //3.乘法:
        temp = data1.multiply(data2);//84
        System.out.println(temp);

        //4.除法
        temp = data1.divide(data2);//1
        System.out.println(temp);

        //5.取模:需要data2不等于0,否则出现异常
        temp = data1.mod(data2);
        System.out.println(temp);//5

        //6.取余:取模与取余一样,最后都是得到了余数的值
        temp = data1.remainder(data2);
        System.out.println(temp);//5

        //7.平方
        //pow里面的值必须大于0,否则宝异常
        temp = data1.pow(2);
        System.out.println(temp);//144

        //8.相反数
        temp = data1.negate();
        System.out.println(temp);//-12

        //9.绝对值
        temp = data1.negate().abs();
        System.out.println(temp);//12
    }

三、BigInteger与int、long类型的相互转换【可能会丢失精度】

① int、long转换为BigInteger:
new BigInteger(int i+""); / new BigInteger(long l+"");

先将int、long转换为String类型、再使用BigInteger的构造方法创建BigInteger类型的数据

② BigInteger转换为int、long类型
  • BigInteger == > int

转换过程中不会报错:int intValue()

转换过程会报错【超过int取值范围】:int intValueExact()

  • BigInteger == > long

转换过程中不会报错:int longValue()

转换过程会报错【超过long取值范围】:int longValueExact()

 //BigInteger与int、long类型的相互转换【可能会丢失精度】
    @Test
    public void test4(){
        //int、long转换为BigInteger类型
        int i = 12;
        long l = 112;
        BigInteger data1 = new BigInteger(i+"");
        BigInteger data2 = new BigInteger(l+"");
        System.out.println(data1);
        System.out.println(data2);

        //BigInteger类型转换为int、long类型
        BigInteger data3 = new BigInteger("1111115213125551");
        BigInteger data4 = new BigInteger("5621312312312312321321378");

        //如果BigInteger类型的数据超过int类型的范围会报错
//        int i1 = data3.intValueExact();
        //如果BigInteger类型的数据超过int类型的范围,不会报错,得到的是一个负数
        int i3 = data3.intValue();

        //如果BigInteger类型的数据超过long类型的范围会报错
//        long i2 = data4.longValueExact();
        //如果BigInteger类型的数据超过long类型的范围,不会报错,得到的是一个负数
        long i4 = data4.longValue();
//        System.out.println(i1);
        System.out.println(i3);
//        System.out.println(i2);
        System.out.println(i4);

    }

四、比较BigInteger类型数据的大小

① 比较大小:int compareTo(BigInteger val)

将此BigInteger与指定的BigInteger进行比较

返回值:1:this大于val;0:等于;-1:this小于val

② 获取较大值:BigInteger max(BigInteger val)

返回较大的值

③ 获取较小值:BigInteger min(BigInteger val)

返回较小的值

    //比较大小
    @Test
    public void test5(){
        BigInteger data1 = new BigInteger("123");
        BigInteger data2 = new BigInteger("1223");

        BigInteger temp;
        int t;

        //data2大:返回-1
        t = data1.compareTo(data2);
        System.out.println(t);
        
        //获取较大值
        temp = data1.max(data2);
        System.out.println(temp);

        //获取较小值
        temp = data1.min(data2);
        System.out.println(temp);
    }

五、BigInteger中的常量值

① ZERO:static BigInteger TEN

BigInteger常数10。

② ONE:static BigInteger ONE

BigInteger常数1。

③ TEN:static BigInteger ZERO

BigInteger常数为0。


    //获取BigInteger的属性
    @Test
    public void test6(){
        //1
        BigInteger data1 = BigInteger.ONE;
        //0
        BigInteger data2 = BigInteger.ZERO;
        //10
        BigInteger data3 = BigInteger.TEN;
        System.out.println(data1);
        System.out.println(data2);
        System.out.println(data3);
    }

六、BigInteger转换为其他类型数据

① 转换为该数据的二进制补码:byte[] toByteArray()

返回一个包含此BigInteger的二进制补码表示的字节数组。

② 转换为bigNum的十进制字符串:String toString()

返回此BigInteger的十进制字符串表示形式。

③ 转换为bigNum的radix进制字符串形式:String toString(int radix)

返回给定进制的BigInteger的String表示形式。

④ 将bigNum转换为float:float floatValue()

将此BigInteger转换为 float 。

⑤ 将bigNum转换为double:double doubleValue()

将此BigInteger转换为 double

 //BigInteger转换为其他类型的数据
    @Test
    public void test7(){
        BigInteger data1 = new BigInteger("33");
        int radix = 2;

        //转换为二进制补码形式
        byte[] bytes = data1.toByteArray();
        System.out.println(Arrays.toString(bytes));

        //转换为十进制字符串形式
        String str = data1.toString();
        System.out.println(str);

        //转换为float类型
        Float f = data1.floatValue();
        System.out.println(f);

        //转换为double类型
        Double d = data1.doubleValue();
        System.out.println(d);
    }

七、二进制运算:与、或、非、异或、取反等

① 按位与运算:BigInteger and(BigInteger val)

返回值为 (this & val)

② 按位或运算:BigInteger or(BigInteger val)

返回值为 (this | val)

③ 按位异或运算:BigInteger xor(BigInteger val)

返回值为 (this ^ val)

④ 按位取反:BigInteger not()

返回值为 (~this)

⑤ 左移n位:BigInteger shiftLeft(int n)

返回值为 (this << n)

⑥ 右移n位:BigInteger shiftRight(int n)

返回值为 (this >> n)

    //二进制运算操作
    @Test
    public void test8(){
        BigInteger data1 = new BigInteger("12");
        BigInteger data2 = new BigInteger("4");
        BigInteger temp;

        //按位与
        temp = data1.and(data2);
        System.out.println(temp);

        //按位或
        temp = data1.or(data2);
        System.out.println(temp);

        //按位异或
        temp = data1.xor(data2);
        System.out.println(temp);

        //按位取反
        temp = data1.not();
        System.out.println(temp);

        //左移2位
        temp = data1.shiftLeft(2);
        System.out.println(temp);

        //右移2位
        temp = data1.shiftRight(2);
        System.out.println(temp);
    }

八、权限控制

① setBit():BigInteger setBit(int n):将set进去的变量作为二进制数,计算它们的和,以十进制显示

返回一个BigInteger,其值等于具有指定位集合的BigInteger。

② testBit():boolean testBit(int n):验证this的二进制组成元素中是否包含传入的变量

返回 true当且仅当指定的位被设置。

③ setBit()、testBit()源码分析:
	//权限控制源码分析:
	
	//1.setBit()原理:计算this与2的n次方的和
	public BigInteger setBit(int n) {
		if (n < 0)
			throw new ArithmeticException("Negative bit address");

		int intNum = n >>> 5;
		int[] result = new int[Math.max(intLength(), intNum+2)];

		for (int i=0; i < result.length; i++)
			result[result.length-i-1] = getInt(i);

		result[result.length-intNum-1] |= (1 << (n & 31));

		return valueOf(result);
	}
	
	//2.testBit()原理:计算this的值中是否包含2的n次方
	public boolean testBit(int n) {
		if (n < 0)
			throw new ArithmeticException("Negative bit address");

		return (getInt(n >>> 5) & (1 << (n & 31))) != 0;
	}

④ setBit()、testBit()使用:
    //权限控制
    @Test
    public void test9(){
        //使用setBit封装的数据需要是>=0,否则会报错
        BigInteger data1 = BigInteger.ZERO;
        BigInteger data2 = data1.setBit(2);

        data2 = data2.setBit(5);
        data2 = data2.setBit(11);
        data2 = data2.setBit(22);
        System.out.println(data2);
        //原理:4196388 = 0 + 2^2 + 2^5 + 2^11 + 2 ^22

        //取值验证
        System.out.println(data2.testBit(2));
        System.out.println(data2.testBit(5));
        System.out.println(data2.testBit(11));
        System.out.println(data2.testBit(22));
        System.out.println(data2.testBit(23));
    }
⑤ setBit(),testBit()权限管理:

权限设置:把具体的菜单权限经过计算得到一个正整数值,存储在数据库相应字段中,计算参数为菜单的id。

例如,如果一个用户有多个权限的话,比如1,2权限。那么我们设置权限值的时候就是num.setBit(1),num.setBit(2),然后把返回的num值保存在session中。如果该用户要验证是否有权限的话,只要从session中取出保存的num,然后执行下num.testBit(权限值),如果返回true就是有权限的,否则无权限。

例子如下:

public static void main(String[] args)
{
  //创建一个初值>=0
    BigInteger num = new BigInteger("0");
  //给该用户有权限2
    num = num.setBit(2);
  //该用户有权限1
    num = num.setBit(1);
    System.out.println(num);
  //判断该用户是否有权限2
    System.out.println(num.testBit(2));
  //判断该用户是否有权限1
    System.out.println(num.testBit(1));
  //判断该用户是否有权限3
    System.out.println(num.testBit(3));
}

九、小结:

① BigInteger的方法的返回值会产生一个新的对象,不会对原来的对象造成干扰,具有不可变性。

② 使用BigInteger可以很好的解决大整数加减乘除问题【如果想要了解底层过程的话,可以自行看源码】

③ 菜单的权限控制第一次接触到,感觉还是蛮有意思的,希望有机会尝试尝试。


参考文章:

Java中BigInteger类的使用方法详解,常用最全系列!

setBit testBit权限管理


希望本篇文章对大家有所帮助,后续会继续分享java相关的知识…

如果文章内容有错误的地方,请在留言处留下你的见解,方便大家共同学习。谢谢!

如有侵权或其他任何问题请联系:QQ1370922071,本文主要用于学习交流,转载请声明!

作者:皮皮猫吖


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值