有时候,当我们做题的时候会遇到很简答的代码题,例如A+B,但是题是有前提的,就是两个数特别的大。妈耶~~~
大家都知道,定义一个变量,系统会自动为该变量分配空间,例如:int类型在c中,占2个字节,也就是16位,即可以存储0~216-1这么大的数,如果再大,就算是long long int也会溢出报错。
咋办捏?
这时候,大数问题出来了
C++版
一、大数相加
大数相加思路:
1 2 3 4 5 6 7 8 9 1 5 4 7 8 9 6 3 5 1 2 4 5 8 7 4 2
+ 1 8 9 6 4 5 8 9 6 3 1 4 5 6 3 5 8 9 6 2 9 8
= 1 2 3 4 6 14 16 14 7 6 13 13 13 11 10 10 8 11 4 7 12 14 14 9 13 10
满十向前一位进一
= 1 2 3 4 7 5 7 5 3 7 4 4 4 2 1 0 9 1 4 8 3 5 5 0 4 0
首先,从最低位对应相加,之后再进行每一位判断,若满十,将取余保留,取整加到前一位即可。
(大数输入绝大多数是以字符串接收)
核心代码如下:
string BigNumAdd(const string& strNum1, const string& strNum2)
{string strSum;//用来存储最后的结果int len1 = strNum1.size()-1;//获取第一个数的长度int len2 = strNum2.size()-1;//获取第二个数的长度int bit = 0; //保存进位//从结尾开始每位相加 while (len1>=0 && len2>=0){//分别从两数的末尾开始相加 由于是字符的形式,而接下来需要对数进行取余和取整的操作,所以这时要将每个位求和之后获得整数的形式,需要 -‘0’int tmpSum = strNum1[len1]-'0' + strNum2[len2]-'0' + bit;//求每位的和(要把进位也加上)strSum += tmpSum % 10 + '0';//保存进结果 bit = tmpSum / 10;//求进位 --len1;--len2; }//两个整数长度不相等(肯定有一个已经加完了,不需要再额外加if来判断,因为while就可以判断)while (len1 >= 0)//说明第一个数要大些,这时候,第二个数已经没法与第一数位数对应了{//和上个while循环一样int tmpSum = strNum1[len1]-'0' + bit;//获得数字形式strSum += tmpSum % 10 + '0';//保存进结果 bit = tmpSum / 10;//求进位--len1; }while (len2 >= 0) {//和上个while循环一样int tmpSum = strNum2[len2]-'0' + bit;//获得数字形式strSum += tmpSum % 10 + '0';//保存进结果 bit = tmpSum / 10;//求进位--len2; }//当跳出三个循环之后,bit最后存储的是最高一位数的进位与否,进行判断//最高位有进位if (bit != 0)//需要进位strSum += bit + '0'; //由于咱们是从低位开始以次存入字符串里的,所以最后的输出得逆序输出reverse(strSum.begin(), strSum.end()); //反转return strSum;
}
二、大数相乘
大数相乘思路:
1 2 3 4 5 7 8 9 6 3 5 9 8* 6 3 5 1 4= 4 8 12 16 20 28 32 36 24 12 20 36 32 4与第一个数的各个位相乘
= 1 2 3 4 5 7 8 9 6 3 5 9 8 1与第一个数的各个位相乘
= 5 10 15 20 25 35 40 45 30 15 25 45 40 5与第一个数的各个位相乘
= 3 6 9 12 15 21 24 27 18 9 15 27 24 3与第一个数的各个位相乘
= 6 12 18 24 30 42 48 54 36 18 30 54 48 6与第一个数的各个位相乘
然后,与加法相同,竖行每一列对应为相加,可以进位则向前进位
= 6 15 29 44 63 88 110 134 130 117 110 126 127 86 69 44 32
= 7 8 4 1 3 0 4 8 2 9 3 9 6 3 3 7 2
首先,将相对小的数的最低位与相对大的数的每一位进行相乘,然后相对小的数的倒数第二位数再以次与相对大的数的每一位相乘…直到相对小的数的最高位与相对大的数的每一位相乘之后,再以次求和相加即可。
核心代码如下:
string BigNumMultiply(const string& strNum1, const string& strNum2)
{string strMultiply;//两数相乘最大有m+n位int bit = 0;//保留进位int len1 = strNum1.size()-1;//获取第一个数的长度int len2 = strNum2.size()-1;//获取第二个数的长度//计算每一位 for (int i=0; i<len1+len2+2; ++i){//计算结果的第i位(权值肯定为i,第1位也就是个位权值为0(pow(10, 0))) //等于乘数的第(i~0)位分别与被乘数的第(0~i)位相乘,因为这样每位相乘之后权值仍为i //然后相加再加上前一位的进位,就是结果的第i位//然后%10得出第i位,/10得到进位int tmp = 0;for (int j=i; j>=0; --j){//如果下标超出字符串的范围 j为num1的下标, i-j为num2的下标,然后两数相乘 if (j>len1 || (i-j)>len2)continue;//还要注意字符串数字的最高位在字符串的最低位所以得用len减去 tmp += (strNum1[len1-j]-'0') * (strNum2[len2-(i-j)]-'0');//从低位开始加,一列一列相加,相错相乘再相加}//加上进位tmp += bit;//为了防止最后一位是0,但是却加上了if (tmp == 0 && i == len1+len2+1) //最后一位,也就是最高位为0,则没必要往strMultiply 该字符串里面存,因为逆序输出的时候,0是最高位,没有意义的。break;//求余得到结果的第i位strMultiply += tmp % 10 + '0';//计算新的进位bit = tmp / 10;
}//反转reverse(strMultiply.begin(), strMultiply.end()); return strMultiply;
}
三、大数阶乘
核心代码如下:
string rlt("1");string opNum;for (int i=1; i<=n; ++i){//ss不可以定义在for循环外stringstream ss; ss << i;ss >> opNum;rlt = BigNumMultiply(rlt, opNum); }
Java版
一、大数相乘
计算两个非负整数 A,B的乘积,A,B可能会很大。
输入格式
第一行输入一个非负整数 A。
第二行输入一个非负整数 B。
A,B的长度不大于 500。
输出格式
输出 A×B 的值。
样例输入
4321
1234
样例输出
5332114
代码如下:
import java.math.BigInteger;//导入相关的BigInteger包
import java.util.Scanner;//导入扫描仪Scanner
public class main {public static void main(String[] args) { Scanner sq=new Scanner(System.in); BigInteger a,b,result2; a=sq.nextBigInteger(); b=sq.nextBigInteger(); result2=a.multiply(b); System.out.println(result2); }
}
二、大数相加
计算两个非负整数A,B的和。不过这一次有些特殊A,B可能会很大。
输入格式
第一行输入一个非负整数A。
第二行输入一个非负整数B。
A,B的长度不大于 500。
输出格式
输出A+B的值。不要有多余的前导零。
样例输入
123000000000
1234000000000
样例输出
1357000000000
代码如下:
import java.math.BigDecimal;
import java.util.Scanner;
public class bigteger {public static void main(String[] args) {BigDecimal a,b,c;Scanner sq=new Scanner(System.in);while(true){a=sq.nextBigDecimal();b=sq.nextBigDecimal();c=a.add(b);if(c.compareTo(BigDecimal.ZERO) == 0)//此处equal是不可以的,因为会将精度也算进去System.out.println("0");elseSystem.out.println(c.stripTrailingZeros().toPlainString());}
}
}
BigDecimal是处理高精度的浮点数运算的常用的一个类
一般直接使用 BigDecimal.toString()方法即可以完成浮点数的打印。System.out.println( new BigDecimal("100.000").toString()); 100.000System.out.println( new BigDecimal("100.000").stripTrailingZeros().toString()); 1E+2stripTrailingZeros()函数就是用于去除末尾多余的0的,而输出是科学计数法System.out.println( new BigDecimal("100.000").stripTrailingZeros().toPlainString()); 100
用toPlainString()函数代替toString(),避免输出科学计数法的字符串
(保留小数点的方法)代码如下:
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {public static void main(String[] args) {BigDecimal a,b,c;Scanner sq=new Scanner(System.in);a=sq.nextBigDecimal();b=sq.nextBigDecimal();c=a.add(b);BigDecimal e=c.setScale(2,BigDecimal.ROUND_HALF_UP);//里面的2这个参数代表保留两位小数System.out.println(e);}
}
详细博文参考:https://blog.csdn.net/qq_39101581/article/details/78624617