引言
相信各位算法大佬的算法学习第一课就是大数运算(高精度),同时大佬们对于大数都有自己的板子,但是今天我要给大家介绍一个新的东西可以高效解决大数问题,那就是java提供的BigInteger类,这个类的底层是将大数转换二进制补码的形式来存储,同时提供了加减乘除模以及幂运算的相关接口。下面就开始正文
入门演示
小编觉得大家平时在写算法题时语言都是用c++,所以这里的板子也就用c++给出了。我们来看一下下面这道题
这道题相信对于大家来说都是小儿科,我就直接给出c++答案
#include <bits/stdc++.h>
using namespace std;
vector<int> add(vector<int> &a, vector<int> &b) {
vector<int> c;
int t = 0;
for (int i = 0; i < a.size() || i < b.size(); i++) {
if (i < a.size())t += a[i];
if (i < b.size())t += b[i];
c.push_back(t % 10);
t /= 10;
}
if (t) c.push_back(t);
return c;
}
int main() {
string a, b;
cin >> a >> b;
vector<int> ret1, ret2;
for (int i = a.size() - 1; i >= 0; i--)ret1.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--)ret2.push_back(b[i] - '0');
auto c = add(ret1, ret2);
for (int i = c.size() - 1; i >= 0; i--)
cout << c[i];
return 0;
}
相信大家一看就知道add函数就是高精度加法的板子。下面我们来看看用BigInteger是怎么样的。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.math.BigInteger;
public class Main {
public static void main(String[] args) throws IOException {
read rf = new read();
String a = rf.nextLine();
String b = rf.nextLine();
BigInteger bigInteger1 = new BigInteger(a);
BigInteger bigInteger2 = new BigInteger(b);
System.out.println(bigInteger2.add(bigInteger1));
}
}
class read {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer st = new StreamTokenizer(bf);
String next() {
return st.sval;
}
String nextLine() throws IOException {
return bf.readLine();
}
int nextInt() throws IOException {
st.nextToken();
return (int) st.nval;
}
long nextLong() throws IOException {
st.nextToken();
return (long) st.nval;
}
double nextDouble() throws IOException {
st.nextToken();
return st.nval;
}
}
read是我的快读类,有想详细了解的可以看我主页有详细讲解。我们会发现用BigInteger只有一行那就是调用一个add方法就可以了。但是到这里你可能会觉得这没什么,接下来我们来看下面这道题。
这道题的两个输入都是大数,但是我们平常大多遇到的乘法都是小数乘大数,就像下面这样
#include<bits/stdc++.h>
using namespace std;
vector<int> mul(vector<int> &a, int b) {
vector<int> c;
int t = 0;
for (int i = 0; i < a.size() || t; i++) {
if (i < a.size()) t = a[i] * b + t;
c.push_back(t % 10);
t /= 10;
}
return c;
}
int main() {
string s;
int b;
cin >> s >> b;
vector<int> a;
for (int i = s.size() - 1; i >= 0; i--) a.push_back(s[i] - '0');
auto c = mul(a, b);
for (int i = c.size() - 1; i >= 0; i--) cout << c[i];
return 0;
}
而这道题是两个大数相乘,如果这时我们还用之前的模板解决就会得到下面这个结果。
相信这时你会说我们可以去准备大数乘大数的模板,但是那样的代码量会多很多,同时我们也增加了我们debug的难度, 所以先别急,我们来看看如果我们使用BIgInteger会是什么样的呢?
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.math.BigInteger;
public class Main {
public static void main(String[] args) throws IOException {
read rf = new read();
String a = rf.nextLine();
String b = rf.nextLine();
BigInteger bigInteger1 = new BigInteger(a);
BigInteger bigInteger2 = new BigInteger(b);
System.out.println(bigInteger2.multiply(bigInteger1));
}
}
class read {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer st = new StreamTokenizer(bf);
String next() {
return st.sval;
}
String nextLine() throws IOException {
return bf.readLine();
}
int nextInt() throws IOException {
st.nextToken();
return (int) st.nval;
}
long nextLong() throws IOException {
st.nextToken();
return (long) st.nval;
}
double nextDouble() throws IOException {
st.nextToken();
return st.nval;
}
}
我们只需要调用一个multiply方法就可以了,就是如此简单,相信看到这里你一定想迫不及待就想学习一下BigInteger了吧。
了解BigInteger
BigInteger是java提供的专门处理大数的类,但在实际开发当中他的好兄弟BigDecimal更受关注,因为可以实现小数的精度准确,这个我们下次再说,这次我们主要来了解一下BigInteger。虽然提供了好几个构造方法,但我们主要来讲一下字符串作为参数的就好了
BigInteger(String val) 将 BigInteger 的十进制字符串表示形式转换为 BigInteger。 |
就是给它传一个用字符串表示的数字,然后他就会给我们创建一个BigInteger对象,话不多说上代码,玩的就是真实。
public static void main(String[] args) throws IOException {
String s = "111111111111111111111111111111111111111111111111111111111111111";
BigInteger bigInteger = new BigInteger(s);
System.out.println(bigInteger);
}
然后BigInteger类给我们提供了许多数学运算的接口,我们一个一个来讲一下
加法
如果我们要进行加法运算,Biginteger给我们提供了add方法,怎么使用呢?来上代码,玩的就是真实
public static void main(String[] args) throws IOException {
BigInteger a = new BigInteger("1");
a.add(BigInteger.valueOf(1));
System.out.println(a);
}
这时就会有人说你这计算结果也不对啊,你到底行不行啊!是啊,计算结果为什么不对呢?
注意:那是因为BigInteger提供的接口每次计算完的结果存放在另外一个BigInteger里,我们要重新接收一下,就像下面这样
或者你也可以直接打印输出。
减法
减法也一样只要调用一下subtract方法就可以了,和add简直不要一模一样,话不多说
public static void main(String[] args) throws IOException {
BigInteger a = new BigInteger("1");
a = a.subtract(BigInteger.valueOf(1));
System.out.println(a);
}
不要忘了接收一下结算结果。
乘法
也是一模一样,方法名不同罢了,乘法叫做multiply。
public static void main(String[] args) throws IOException {
BigInteger a = new BigInteger("1");
a = a.multiply(BigInteger.valueOf(1));
System.out.println(a);
}
不要忘了接收一下结算结果。
除法
同样也是一模一样,方法名不同罢了,除法叫做divide,整除,不要余数。
public static void main(String[] args) throws IOException {
BigInteger a = new BigInteger("5");
a = a.divide(BigInteger.valueOf(1));
System.out.println(a);
}
不要忘了接收一下结算结果。
取模
取模与上面那几个有所不同,调用的方法名叫做divideAndRemainder,看方法名顾名思义,就是除数和余数啦,这个方法会返回一个BigInteger数组,这个数组的长度是二,第一个数是除数,第二个数是余数。
public static void main(String[] args) throws IOException {
BigInteger a = new BigInteger("11");
BigInteger[] arr = a.divideAndRemainder(BigInteger.valueOf(3));
for (int i = 0; i < arr.length; i++) {
System.out.println(i + " : " + arr[i]);
}
}
幂运算
和加减乘除一样,方法名不同罢了,幂运算叫做pow
public static void main(String[] args) throws IOException {
BigInteger a = new BigInteger("2");
a = a.pow(3);
System.out.println(a);
}
不要忘了接收一下结算结果。
好了,只要掌握上面这几个方法就足够去应付我们平时遇到的大部分有关大数运算的题目,至于BigInteger的好兄弟BigDecimal就看情况,应该不久也会出。
最后谢谢大家看到最后,制作不易,如果觉得还不错,可以三连支持一下。
乘骐骥以驰骋兮,来吾道夫先路!