java大整數四則運算
前言:
目前計算機中資料儲存最大為64位,對超過64位的數進行運算就會導致運算結果錯誤。所以針對大整數進行四則運算是十分必要的。這也是面試中非常經典的問題,所以這次我們特意整理了關於大整數的四則運算。所謂的大整數的運算其實就是模擬了人腦進行數字計算用到的規則。
1.大整數的儲存
由於後續很多運算都是從低位開始,所以我們設計該儲存方式為從低位向高位依次存放在陣列。
public class bigInt{
int [] data=null;//存放資料(從低位到高位依次存放)
int symbol=1;//1代表整數,0代表負數
}
2.判斷大整數大小
大整數的絕對值大小判斷在後面將大量的應用到,後續運算都是按照第一運算元大於第二運算元(無符號數)。java中提供了comparable介面比較大小,所以我們實現介面即可。
3.大整數類設計與實現
class bigInt implements Comparable<bigInt>{
int [] data=null;//存放資料(逆序放置)
int symbol=1;//1代表整數,0代表負數
public bigInt(){
}
public bigInt(String value){
examSymbol(value);
}
public void examSymbol(String value){//檢測符號問題
int start=0;//資料的開始位置
char head=value.charAt(0);
if(head=='+'||head=='-'){
start=1;
if(head=='-')
symbol=-1;
}
int len=value.length()-start;
data=new int[len];//資料長度為Len
for(;start<value.length();start++){
data[--len]=value.charAt(start)-'0';
}
}
@Override
public int compareTo(bigInt b1) {//比較的是絕對值
//找到最高位的第一個非0開始
int a_max=findMax(this.data);
int b_max=findMax(b1.data);
if(a_max!=b_max)
return a_max>b_max?1:-1;
//從高位開始比較
int c1,c2;
for(int k=a_max;k>=0;k--){
c1=this.data[k];
c2=b1.data[k];
if (c1!=c2)
return c1>c2?1:-1;
}
return 0;
}
#大整數中有效數字位,最高位不為0
public int findMax(int []data){
int m=data.length-1;
for(;m>=0;m--){
if(data[m]!=0)
return m;
}
return 0;
}
@Override
public String toString() {
char symbol='+';
if (symbol==-1)
symbol='-';
StringBuilder sb=new StringBuilder();
sb.append(symbol);
int k=findMax(data);//找到第一個不為0的高位
for(;k>=0;k--){//從高位到低位依次輸出
sb.append(data[k]);
}
return sb.toString();
}
4.大整數同號相加
思路:假設大整數為a1,a2,預設|a1|>|a2|,先比較大小,若|a1|<|a2|,則交換2個運算元順序,始終保持第一運算元大於第二運算元。
加法規則:分別從2個數的低位開始進行逐位相加,並加上前一位的進位,如果相加和超過9,則記錄進位數,用於下一次進位。最後,如果最高位產生進位,則在最高位前面新增一個最高位1。
public bigInt unSignAdd(bigInt b1,bigInt b2){
// 儲存累加的結果
StringBuilder sb=new StringBuilder();
// if(b1.compareTo(b2)<0){//預設b1>b2
// bigInt temp=b1;
// b1=b2;
// b2=temp;
// }
int m=b1.data.length;
int n=b2.data.length;
//從低位開始相加,設定進位
int carry=0;//記錄上一位的進位
int b1_v,b2_v=0;
int currentv=0;//當前位累加和
for(int i=0;i<m;i++){
b2_v=0;
b1_v=b1.data[i];
if(i<n)
b2_v=b2.data[i];
currentv=b1_v+b2_v+carry;
if(currentv>9){//當前和產生進位
carry=currentv/10;
currentv=currentv%10;
}
else
carry=0; //當前位未產生進位,則置標記
sb.insert(0,currentv);
} //end for
//如果2數相加最高位產生進位
if(carry==1){
sb.insert(0,1);
}
char symbol='+';//同號加法
if(b1.symbol==-1)
symbol='-';
sb.insert(0,symbol);
return new bigInt(sb.toString());
}
5.大整數異號相加
設a1,a2為2個大整數,且2符號相反,|a1|>=|a2|,如果|a1|=|a2|,則結果為0。如果不等,則按照下面規則進行運算。使用無符號大數-無符號小數,最後運算結果的符號有絕對值大的數的符號來決定。
假設我們計算3+(-2),由於2個運算元異號,則進行減法法則3-2=1,最後結果符號根據3來決定,所以結果為1。
所以這裡異號相加需要使用大整數減法的法則。
減法規則:分別從2個數的低位開始進行逐位相減,並減去前一位的借位,如果值小於0,則向高位借一位,記錄借位數值。最後結果符號由大數(絕對值)決定。
public bigInt unSignSub(bigInt b1,bigInt b2){
StringBuilder sb=new StringBuilder();
// if(b1.compareTo(b2)<0){//預設b1>b2
// bigInt temp=b1;
// b1=b2;
// b2=temp;
// }
int borrow=0;
int m=b1.data.length;
int n=b2.data.length;
int b1_v,b2_v;//當前對應位的值
int currentV=0;
for(int i=0;i<m;i++){
b1_v=b1.data[i];
b2_v=0;
if(i<n)
b2_v=b2.data[i];
currentV=b1_v-b2_v-borrow;//相減之和的當前位的值
if(currentV<0){//該位不夠減
currentV=currentV+10;//向高位借
borrow=1;//借位1
}
else{
borrow=0;
}
sb.insert(0,currentV);
}
//結果符號由大數符號決定
char symbol=b1.symbol==1?'+':'-';
sb.insert(0,symbol);
return new bigInt(sb.toString());
}
6.大整數有符號相加
有符號大整數a1,a2相加的計算規則更負責些。根據a1,a2(|a1|>|a2|)是否同號指定不同的計算規則。
1)a1,a2同號,則直接使用上面的大整數無符號相加的規則。
2)a1,a2異號.則使用大整數異號規則處理。
/**
* 有符號的加法
* @return
*/
public bigInt add(bigInt b1,bigInt b2){
int c=b1.compareTo(b2);
if(c<0){ //保證大數在前,小數在後
bigInt temp=b1;
b1=b2;
b2=temp;
}
//判斷是否同號
if(b1.symbol*b2.symbol==-1){//異號
if(c==0)//a1,a2的絕對值相等,則結果為0
return new bigInt("0");
return unSignSub(b1,b2);
}
else//同號
return unSignAdd(b1,b2);
}
7.大整數有符號減法
減法可以轉化為加法進行運算,如3-5=3+(-5),這樣就就轉化為加法進行運算。即只需要將第二運算元符號反置即可。
/**
* 有符號減法
*/
public bigInt sub(bigInt b1,bigInt b2){
b2.symbol*=-1;
bigInt r=add(b1,b2);//變成加法運算
b2.symbol*=-1;//將修改的符號變過來
return r;
}
8.大整數乘法
乘法法則:模擬手動計算乘法,乘數每一位與被乘數每一相乘的結果累加到相應位上。最後再針對每一位上的結果進行進位即可。
乘法過程:
/**
* 大整數相乘
* @param a1
* @param a2
* @return
*/
public bigInt multi(bigInt b1,bigInt b2){
//大數放前面
if(b1.compareTo(b2)<0){
bigInt temp=b1;
b1=b2;
b2=temp;
}
int m=b1.data.length;
int n=b2.data.length;
int []result=new int[m+n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
result[i+j]+=b1.data[i]*b2.data[j];
}
}
//考慮進位
int carry=0;
StringBuilder sb=new StringBuilder();
for(int k=0;k<m+n;k++){
result[k]+=carry;
if(result[k]>9){
carry=result[k]/10;
result[k]=result[k]%10;
}
else
carry=0;
sb.insert(0,result[k]);
}
bigInt r=new bigInt(sb.toString());
r.symbol=b1.symbol*b2.symbol;
return r;
}
9.大整數除法
採用試商法,設被除數為d,除數為v,從高位開始取被除數的下一位與當前餘數連線形成p,
規則:用試商法求p除以除數v如果p大於v,使用遞減法(不斷使用p=p-v)來求出p/v的商。記錄當前的商和餘數,以此類推,直到計算完最後一位。
除法過程:
public bigInt div(bigInt b1,bigInt b2){
int m=b1.data.length;
int n=b2.data.length;
StringBuilder result=new StringBuilder();//儲存商
bigInt yu=new bigInt(); //存放餘數
yu.data=new int[n+1];//餘數位數為除數+1
int k=0;
for(int i=m-1;i>=0;i--){ //從高位開始
//確保餘數的位數為n+1位,如果不等則進行復制
if(yu.data.length!=n+1){
int len=yu.findMax(yu.data);
int mydata[]=new int[n+1];
for(i=0;i<=len;i++){
mydata[i]=yu.data[i];
}
yu.data=mydata;
}
//將取得的數放入低位和餘數構成被除數p
System.arraycopy(yu.data,0,yu.data,1,n);
yu.data[0]=b1.data[i];
k=0;//試商的結果
while(yu.compareTo(b2)>=0){
yu=sub(yu,b2);//不斷相減,來求商.
k+=1;
}
result.append(k);
}
return new bigInt(result.toString());
}
相關文章
- Java簡單四則運算Java
- 四則運算
- 四則運算計算器
- 四則運算專案
- 四則運算手冊
- OJ1038 四則運算
- 複數的四則運算(C語言實現)C語言
- python四則運算生成器Python
- 結對專案四則運算
- Shell階段02 shell變數運算(整數運算/小數運算), shell變數案例變數
- 軟體工作四則運算測試
- 結對程式設計-四則運算程式設計
- 四則運算+-×÷同時成立的四連環(2)
- 四則運算+-×÷同時成立的四連環(4)
- 四則運算+-×÷同時成立的四連環(3)
- 四則運算+-×÷同時成立的四連環(1)
- 四則運算+-×÷同時成立的四連環(6)
- 演算法(3)簡單四則運算演算法
- python資料型別和四則運算Python資料型別
- 結對編碼-四則運算 2252118 2252121
- 課後作業——30道四則運算
- XJSON 是如何實現四則運算的?JSON
- 正則實現數學運算
- 或與運算和安全整數(數的影子)
- 結對程式設計 小學四則運算程式設計
- [記錄] 通用封裝函式——四則運算封裝函式
- C/C++模運算(正負整數)C++
- 用python實現四則運算的生成與判定Python
- 圖文剖析 big.js 四則運算原始碼JS原始碼
- php鏈式操作實現四則鏈式運算PHP
- 隨機生成三百道四則混合運算題目程式隨機
- java基礎(四) java運算順序的深入解析Java
- Linux從入門到精通系列之SHELL程式設計變數與四則運算Linux程式設計變數
- JS四則運算與四捨五入精度問題及解決方案JS
- Java 基礎 之 算數運算子Java
- C語言程式設計-長整數加法運算C語言程式設計
- 結對程式設計--自動生成小學四則運算程式設計
- java大數運算詳解【其十】大數除法之Burnikel-Ziegler除法演算法Java演算法