众所周知,所有的编程语言中,每一种基本数据类型都有范围,就拿整数来说,int型的数据能表示的范围是有限的,但有时我们可能进行很大的整型数据的运算。当然,有人会说,有long int 呀?是的,但long int 能表示的数据仍然是有限的。我们要进行一万位的整型的加、减、乘、除的运算怎么办?此时我们就需要考虑如何实现大整型数据的运算。
要解决这个问题,就必须考虑别的思路或方法,最普遍的做法就是采用数组存储每一位的数据,这样,即使再大的整型也能进行运算。
整体思路:
1)将一个数字字符串(用字符串接收输入的数据)每一位分割存入整型数组中。
一、加法运算:
加法运算就像小学学加法运算时的方法。例如有两个整型数组NumA[3] = { 1,3,9},NumB[3] = { 4,7, 2},保存结果的Result[6];记录中间结果的整型变量Temp。
A.先让个位运算:
1 3 9
4 7 2
1[进位] 1[本位]
int low = 0; //记录低位的进位数字
Temp = NumA[2] + NumB[2];
if(Temp >= 10) //有进位
{
Result[5] = Temp % 10 + low;
Result[4] += Temp / 10;
}
B.然后让十位运算,原理和个位运算一样。依次加完所有的数即可完成加法运算。
二、减法运算:
减法运算和加法类似,只不过一个是加,一个是减,一个是进位,另一个是借位。
三、乘法运算:
乘法运算稍微复杂一些。但原理和加法类似,只不过是多加法运算的组合。
就拿上面的书来说:
1 3 9
4 7 2
2 6+1(低位进的数) 8[本位]
7+2 1+6 3
4+1 2+3 6
6 5 6 0 8
用被乘数的个位与乘数的每一位相乘。
int MidResult[5]; //保存中间计算结果
int low = 0; //低位的进位
MidResult[4] = NumA[2] * NumB[2] % 10 + low;
low = NumA[2] / NumB[2];
MidResult[3] = NumA[1] * NumB[2] % 10 + low;
依次计算,得到中间结果MidResult;
low = 0;
Result[4] = (Result[4] +MidResult[4] + low) % 10;
low = Result[4] / 10;
Result[3] = (Result[3] + MidResult[4] + low)% 10;
....
上面是NumB个位计算结果,若是十位,则 Result从Reslut[3]与 MidResult[4]加起。
依次计算就可以得到结果。
四、除法:
这和小学学的除法运算也是一样的。
1 1 3
9 [ 1 0 2 4
1 2
9
3 4
2 7
7
正如上面的运算一样,采用从0 - 9 依次在每一位试,直到有10 - 1[试]*9 的值 >= 0;则改位商 1,依次计算。
具体的代码如下:
/**
* @计算超大整型
*/
public class LargeInteger {
String FirstNumStr; //第一个数的字符串
LargeInteger(String var){ //构造方法(给第一个数字符串赋值)
this.FirstNumStr = var;
}
/**
* 加方法
* @param SecondNumStr 被加数
* @return 相加的结果
*/
public String add(String SecondNumStr){ //加方法
int LengthA = FirstNumStr.length(); //求出第一个数字符串长度
int LengthB = SecondNumStr.length();//求出第二个数字符串长度
boolean IsMinus = false; //是否带负号
if((FirstNumStr.charAt(0) == '-') && (SecondNumStr.charAt(0) == '-')){//都带负号
IsMinus = !IsMinus;
}else if(FirstNumStr.charAt(0) == '-'){ //第一个数带负号
FirstNumStr = FirstNumStr.substring(1);
String second = FirstNumStr;
FirstNumStr = SecondNumStr;
return subtract(second);
}else if(SecondNumStr.charAt(0) == '-'){ //第二个数带负号
SecondNumStr = SecondNumStr.substring(1);
return subtract(SecondNumStr);
}
int MaxLength = LengthA >= LengthB?LengthA:LengthB; //求出最大的长度
MaxLength += 1; //加1是为了给可能的进位留出一位
int []FirstNum = new int[MaxLength]; //定义第一个数整型数组
int []SecondNum = new int[MaxLength]; //定义第二个数整型数组
int []Result = new int[MaxLength]; //定义存放结果数组
int MidResult = 0; //中间结果
int num = 0; //记录将字符转为整型的数
for(int i = LengthA-1,j = MaxLength-1; i >= 0; i--,j--){ //将第一个数字符串转为整型数组
switch(FirstNumStr.charAt(i)){
case '0':num = 0;break;
case '1':num = 1;break;
case '2':num = 2;break;
case '3':num = 3;break;
case '4':num = 4;break;
case '5':num = 5;break;
case '6':num = 6;break;
case '7':num = 7;break;
case '8':num = 8;break;
case '9':num = 9;break;
default:num = 0;break;
}
FirstNum[j] = num;
}
num = 0;
for(int i = LengthB-1,j = MaxLength-1; i >= 0; i--,j--){//将第二个数字符串转为整型数组
switch(SecondNumStr.charAt(i)){
case '0':num = 0;break;
case '1':num = 1;break;
case '2':num = 2;break;
case '3':num = 3;break;
case '4':num = 4;break;
case '5':num = 5;break;
case '6':num = 6;break;
case '7':num = 7;break;
case '8':num = 8;break;
case '9':num = 9;break;
default:num = 0;break;
}
SecondNum[j] = num;
}
for(int i = MaxLength-1; i >= 0; i--){ //从个位开始加
MidResult = FirstNum[i] + SecondNum[i]; //记录两数相加的中间结果
if(MidResult >= 10){ //进位
Result[i] = MidResult % 10; //本位的数
FirstNum[i-1] = FirstNum[i-1] + 1; //进位
}else{
Result[i] = MidResult; //没有进位直接赋值
}
}
String ResultStr = "";
if(IsMinus){ //
ResultStr = "-";
}
boolean flag = false;
for(int j = 0 ; j < MaxLength; j++){ //将整型数组转为字符串
if(Result[j] != 0){ //数组前面有0不赋值给字符串
flag = true;
}
if(flag){
ResultStr += Result[j];
}
}
return ResultStr;
}
/**
* 减方法
* @param SecondNumStr
* @return 相减的结果
*/
public String subtract(String SecondNumStr){
int LengthA = FirstNumStr.length(); //求出第一个数字符串长度
int LengthB = SecondNumStr.length();//求出第二个数字符串长度
if((FirstNumStr.charAt(0) == '-') && (SecondNumStr.charAt(0) == '-')){
String second = FirstNumStr;
FirstNumStr = SecondNumStr.substring(1);
return add(second);
}else if(FirstNumStr.charAt(0) == '-'){
SecondNumStr = "-"+SecondNumStr;
return add(SecondNumStr);
}else if(SecondNumStr.charAt(0) == '-'){
SecondNumStr = SecondNumStr.substring(1);
return add(SecondNumStr);
}
int MaxLength = LengthA >= LengthB?LengthA:LengthB; //求出最大的长度
int []FirstNum = new int[MaxLength]; //定义第一个数整型数组
int []SecondNum = new int[MaxLength]; //定义第二个数整型数组
int []Result = new int[MaxLength]; //定义存放结果数组
int MidResult = 0; //中间结果
int num = 0; //记录将字符转为整型的数
for(int i = LengthA-1,j = MaxLength-1; i >= 0; i--,j--){ //将第一个数字符串转为整型数组
switch(FirstNumStr.charAt(i)){
case '0':num = 0;break;
case '1':num = 1;break;
case '2':num = 2;break;
case '3':num = 3;break;
case '4':num = 4;break;
case '5':num = 5;break;
case '6':num = 6;break;
case '7':num = 7;break;
case '8':num = 8;break;
case '9':num = 9;break;
default:num = 0;break;
}
FirstNum[j] = num;
}
num = 0;
for(int i = LengthB-1,j = MaxLength-1; i >= 0; i--,j--){//将第二个数字符串转为整型数组
switch(SecondNumStr.charAt(i)){
case '0':num = 0;break;
case '1':num = 1;break;
case '2':num = 2;break;
case '3':num = 3;break;
case '4':num = 4;break;
case '5':num = 5;break;
case '6':num = 6;break;
case '7':num = 7;break;
case '8':num = 8;break;
case '9':num = 9;break;
default:num = 0;break;
}
SecondNum[j] = num;
}
boolean FirstNumLarger = false;
Breakflag:for(int i = 0; i <MaxLength; i++){ //判断第一个数是否大于第二个数
if(FirstNum[i] > SecondNum[i]){
FirstNumLarger = true;
break Breakflag;
}else if(FirstNum[i] == SecondNum[i]){
continue;
}else{
break Breakflag;
}
}
for(int i = MaxLength-1; i >= 0; i--){ //从个位开始加
if(FirstNumLarger){ //大数减小数
MidResult = FirstNum[i] - SecondNum[i]; //记录两数相减的中间结果
}else{
MidResult = SecondNum[i] - FirstNum[i];
}
if(MidResult < 0){ //借位
Result[i] = 10 + MidResult ; //本位的数
if(FirstNumLarger){
FirstNum[i-1] = FirstNum[i-1] - 1; //借位
}else{
SecondNum[i-1] = SecondNum[i-1] - 1;
}
}else{
Result[i] = MidResult; //没有进位直接赋值
}
}
String ResultStr = "";
if(!FirstNumLarger){
ResultStr = "-";
}
boolean flag = false;
for(int j = 0 ; j < MaxLength; j++){ //将整型数组转为字符串
if(Result[j] != 0){ //数组前面有0不赋值给字符串
flag = true;
}
if(flag){
ResultStr += Result[j];
}
}
if(ResultStr == "-"){ //相减为0时,赋值0
ResultStr = "0";
}
return ResultStr;
}
/**
* 乘方法
* @param SecondNumStr
* @return 相乘的结果
*/
public String multiply(String SecondNumStr){
boolean IsMinus = false; //是否带负号
if(FirstNumStr.charAt(0) == '-'){
IsMinus = !IsMinus;
FirstNumStr = FirstNumStr.substring(1);
}
if(SecondNumStr.charAt(0) == '-'){
IsMinus = !IsMinus;
SecondNumStr = SecondNumStr.substring(1);
}
int LengthA = FirstNumStr.length(); //求出第一个数字符串长度
int LengthB = SecondNumStr.length();//求出第二个数字符串长度
int MaxLength = LengthA >= LengthB?LengthA:LengthB; //求出最大的长度
MaxLength++; //多预留一个空间
int ResultLength = MaxLength*2; //两个数相乘最多为两个数中最大长度的2倍
int []FirstNum = new int[MaxLength]; //定义第一个数整型数组
int []SecondNum = new int[MaxLength]; //定义第二个数整型数组
int []TempNum = new int[MaxLength]; //临时整型数组存储中间计算结果
int []Result = new int[ResultLength]; //定义存放结果数组
int MidResult = 0; //中间结果
int num = 0; //记录将字符转为整型的数
for(int i = LengthA-1,j = MaxLength-1; i >= 0; i--,j--){ //将第一个数字符串转为整型数组
switch(FirstNumStr.charAt(i)){
case '0':num = 0;break;
case '1':num = 1;break;
case '2':num = 2;break;
case '3':num = 3;break;
case '4':num = 4;break;
case '5':num = 5;break;
case '6':num = 6;break;
case '7':num = 7;break;
case '8':num = 8;break;
case '9':num = 9;break;
default:num = 0;break;
}
FirstNum[j] = num;
}
num = 0;
for(int i = LengthB-1,j = MaxLength-1; i >= 0; i--,j--){//将第二个数字符串转为整型数组
switch(SecondNumStr.charAt(i)){
case '0':num = 0;break;
case '1':num = 1;break;
case '2':num = 2;break;
case '3':num = 3;break;
case '4':num = 4;break;
case '5':num = 5;break;
case '6':num = 6;break;
case '7':num = 7;break;
case '8':num = 8;break;
case '9':num = 9;break;
default:num = 0;break;
}
SecondNum[j] = num;
}
int PriorNum = 0; //进位
int k = ResultLength - 1; //Result[k]从个位向前赋值
for(int i = MaxLength-1; i > 0; i--){ //控制第二个数的个、十、百向前推移
for(int j = MaxLength-1; j > 0; j--){ //使第二个数与第一个数的每一位相乘
MidResult = SecondNum[i]*FirstNum[j]; //保存两个数相乘的中间结果
PriorNum = MidResult / 10; //进位数
// if(MidResult >= 10){ //乘的结果需要进位
TempNum[j] += MidResult % 10; //本位的值
if(TempNum[j] >= 10){ //如果本位的值仍需进位,则再进一位
TempNum[j] = TempNum[j] % 10; //本位的最终值
PriorNum++; //需要的进位数再加一
}
TempNum[j-1] = TempNum[j-1]+PriorNum; //进位
// }
}
int m = k;
for(int n = MaxLength-1; n >= 0; n--,m--){ //将临时存储的数组复制给最终结果数组
Result[m] += TempNum[n]; //赋值
if(Result[m] >= 10){ //若赋值相加需要进位,则进位
Result[m-1] += Result[m]/10; //先进位
Result[m] = Result[m] % 10; //后算本位的值(这两句代码不能颠倒)
}
TempNum[n] = 0; //临时数组置0,以便下一个循环用
}
k--;//下一次临时数组赋值时徐翔高位移一位
}
String ResultStr = "";
if(IsMinus){
ResultStr = "-";
}
boolean flag = false;
for(int j = 0 ; j < ResultLength; j++){ //将整型数组转为字符串
if(Result[j] != 0){ //数组前面有0不赋值给字符串
flag = true;
}
if(flag){
ResultStr += Result[j];
}
}
if(ResultStr == ""){ //相乘为0时,显示0
ResultStr = "0";
}
return ResultStr;
}
/**
* 除方法
* @param SecondNumStr
* @return 除的结果
*/
public String divide(String SecondNumStr){
boolean IsMinus = false; //是否带负号
if(FirstNumStr.charAt(0) == '-'){ //第一个数带了负号
IsMinus = !IsMinus;
FirstNumStr = FirstNumStr.substring(1);
}
if(SecondNumStr.charAt(0) == '-'){ //第二个数带了负号
IsMinus = !IsMinus;
SecondNumStr = SecondNumStr.substring(1);
}
int LengthA = FirstNumStr.length(); //求出第一个数字符串长度
int LengthB = SecondNumStr.length();//求出第二个数字符串长度
if(LengthA < LengthB){ //因为是整除,所以第一个数小与第二个数时,直接返回 0
return "0";
}else if(LengthA == LengthB){ //字符串相等
String result = subtract(SecondNumStr);
if(result.charAt(0) == '-'){ //第一个数小,直接返回0
return "0";
}else if(result.charAt(0) == '0'){ //两个数相等,则返回1
return "1";
}
}
int []Result = new int[LengthA]; //存放最终结果的整型数组
String SubTemp = ""; //存放字串
String Temp = "";
String result = "";
String StoreFirstNumStr = FirstNumStr;//临时存放第一个数
for(int i = LengthB-1 ; i < LengthA; i++ ){
if(i == LengthB-1){
SubTemp = FirstNumStr.substring(0,LengthB);
}else{
FirstNumStr = SubTemp;
SubTemp = subtract(Temp)+StoreFirstNumStr.substring(i,i+1);
}
for(int j = 9; j >= 0 ;j--){ //每一位的商值从9-0挨个试
FirstNumStr = Integer.toString(j); //将整型转为字符串
Temp = multiply(SecondNumStr); //9-0中的数与被除数相乘
FirstNumStr = SubTemp;
result = subtract(Temp);//计算差值
if(result.charAt(0) == '-'){ //若差值为负,则继续
continue;
}else{ //否则,确定商,并跳出循环
Result[i] = j;
break;
}
}
}
String ResultStr = "";//最终返回值的字符串
if(IsMinus){ //计算结果为负
ResultStr = "-";
}
boolean flag = false; //标记变量,标记从Result[0]-Reslult[n-1]哪一位开始不为0,才赋值给ResultStr
for(int j = 0 ; j < LengthA; j++){ //将整型数组转为字符串
if(Result[j] != 0){ //数组前面有0不赋值给字符串
flag = true;
}
if(flag){
ResultStr += Result[j];
}
}
if(ResultStr == ""){ //相乘为0时,显示0
ResultStr = "0";
}
return ResultStr;
}
}
测试代码:
import java.math.BigInteger;
/**
* @author ZhangyaChao(张亚超)
* @version 1.0
* @date 2013/9/17
* @last modify 2013/9/18
*/
public class Basic {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//测试代码
LargeInteger One = new LargeInteger("1024546448494645445444464545454545456546546548897454644");
String Two = "1024546448494645454654";
String result1 = One.add(Two);
String result2 = One.subtract(Two);
String result3 = One.multiply(Two);
String result4 = One.divide(Two);
BigInteger one = new BigInteger("1024546448494645445444464545454545456546546548897454644");
BigInteger Result1 = one.add(new BigInteger("1024546448494645454654"));
BigInteger Result2 = one.subtract(new BigInteger("1024546448494645454654"));
BigInteger Result3 = one.multiply(new BigInteger("1024546448494645454654"));
BigInteger Result4 = one.divide(new BigInteger("1024546448494645454654"));
System.out.println(""+result1+"\n"+Result1+"\n\n");
System.out.println(""+result2+"\n"+Result2+"\n\n");
System.out.println(""+result3+"\n"+Result3+"\n\n");
System.out.println(""+result4+"\n"+Result4+"\n\n");
}
}