大家好,我是皮皮猫吖。
每文一言:希望你活得尽兴,而不是过得庆幸。
本篇文章:
有些算法题中,会使用到大整数加法,在学习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类的使用方法详解,常用最全系列!
希望本篇文章对大家有所帮助,后续会继续分享java相关的知识…
如果文章内容有错误的地方,请在留言处留下你的见解,方便大家共同学习。谢谢!
如有侵权或其他任何问题请联系:QQ1370922071,本文主要用于学习交流,转载请声明!
作者:皮皮猫吖