對於大數字的運算


說明:由於在各種語言中各種整型數據是會受到各種的規範(如在java的整型中byte只有分配一個字節8位,最大的long類型有8個字節也就是說最大能表示2的64次的數)那麼在java中對於超過2的64次方的整數進行運算時該怎麼辦?(通常對這個數被稱爲大數)

    解法:對與一個整數來說,既然不能用一個類型來表示,那麼只能用一個整型的數組來表示來。對與即將操作的數進行分段表示。此處爲了方便表示以及能夠表達我想表達的內容,這裏用int型的數組,對一個不超過16位的數進行加、減、乘(由於乘法對於數的位數影響這裏最大支持8位)除(對於兩個大數來說個人感覺除法沒什麼用處,畢竟除法會影響精度,兩個大數相除結果一定很小。  這裏只寫了一個大數被一個小數除的除法)。




+、-、*、/


   如圖:對一個16位的數進行分割,每4位一組存放在int[] A和B中將結果放在C中。

    注意:由於規定每個數組元素只能存放一個4位數的整數,在進行運算時應該考慮進位和借位的問題,由於在不同運算下產生的借位或進位不同,故在每個方法裏用不同的解決方法。

    加法:

addcheck():解決進位問題

public int addcheck(int a, int b) {
		int flag;
		if (a + b > 10000)     //由於規定了是一個4位數故大於10000就是進位了
			flag = 1;
		else
			flag = 0;
		return flag;
	}

這裏不是用boolean解決是因爲個人感覺返回int的話能直接用了。。。。。

add():解決方法

public void add() {
		int flag = 0;           //flag爲進位
		for (int i = 3; i >= 0; i--) {
			int d = addcheck(a[i], b[i]);
			c[i] = a[i] + b[i] - d * 10000 + flag;
			flag = d;
		}
	}
對與爲什麼不直接把進位賦給flag:flag是低位給高位的標誌,若當前已經產生了進位,那麼應該先考慮把高位給去掉,那麼就有這個d存在的必要了。

    減法:

subcheck():

public int subcheck(int a, int b) {
		if (a - b < 0)
			return -1;
		return 0;
	}

sub():

public void sub() {
		int flag = 0;
		boolean temp = true;
		//考慮到有可能b存放到數比a大先檢測如果是b大那麼將a b互換後在進行減法用temp記錄正負
		for (int i = 0; i < 4; i++) {
			if (a[i] != 0 && b[i] == 0) {
				break;
			}
			if (a[i] < b[i]) {
				c = a;
				a = b;
				b = c;
				temp = false;
				break;
			}
		}
		for (int i = 3; i >= 0; i--) {
			int d = subcheck(a[i], b[i]);
			c[i] = (-d) * 10000 + a[i] - b[i] +flag;
			flag = d;
		}
		System.out.print(temp ? "" : "-");
	}
這裏的d是和加法一樣的考慮。

    乘法:

int[] mulpre():兩個4位的整數相乘會最大會產生一個8位的數,考慮到最大能表示4位,故先寫一個方法返回一個數組,數組裏面有兩個元素:前4位和後4位。

public int[] mulpre(int a,int b){
		int flag=10000;    //表示現在b的位數10000是4位1000是3位
		int tempa[]={0,0};
		int tempb;
		for(int i=1;i<5;i++){
			tempb=b%10;  //取得b中最後的一個數
			b=b/10;      //將b前3位給b
			tempa[0]+=a*tempb/flag;   //計算前4位
			tempa[1]+=a*tempb%flag*(10000/flag); //計算後4位
			flag/=10;
		}
		tempa[0]+=tempa[1]/10000;
		tempa[1]%=10000;
		return tempa;
	}

for循環:求數組內兩個元素的大小的:比如 1234*5678,先拿8和1234乘取後4位爲tempa[1],剩下的是tempa[0],接下來就是7和1234乘取後3位乘10後和原來的tempa[1]相加,剩下的和tempa[0]相加,同理那5和6乘,得到一個包含有兩個4位數的數組。

mul():

public void mul(){
		int flag;
		int[] temp1=mulpre(a[3], b[3]);
		int[] temp2=mulpre(a[2], b[2]);
		int[] temp3=mulpre(a[3], b[2]);
		int[] temp4=mulpre(a[2], b[3]);
		c[3]=temp1[1];
		c[2]=temp1[0]+temp3[1]+temp4[1];
		flag=c[2]/10000;
		c[2]=c[2]%10000;
		c[1]=temp3[0]+temp4[0]+temp2[1]+flag;
		flag=c[1]/10000;
		c[1]=c[1]%10000;
		c[0]=temp2[0];
	}
這裏表示了兩個8位數的乘法(兩個8位數分別放在a和b的後兩個數組單位中)結果c[0]中應該是a[3]*b[3]的前4位,c[1]是a[3]*b[3]後4位 a[3]*b[4]、a[4]*b[3]的前4位之和,c[2]、c[3]都差不多,當然還要考慮進位的問題。

    由於除法只要將c[i]中的數除,將餘數保存,在c[i+1]中使用就可以解決。

div():

public void div(int div){
		int flag=0;
		for(int i=0;i<4;i++){
			a[i]+=flag*10000;
			c[i]=a[i]/div;
			flag=a[i]%div;
		}
	}

全部的代碼:

public class BigInteger {
	public int[] a = new int[4];
	public int[] b = new int[4];
	public int[] c = new int[4];
	public BigInteger(String c, String d) {
		a = prepare(c);
		b = prepare(d);
	}
    //該方法用於切割支付串數組  大數不能被表示嘛  只能用字符串表示了
	public int[] prepare(String s) {
		int[] a = new int[4];
		int l = s.length();
		for (int j = l, i = 3; j > 0 && i >= 0; j -= 4, i--) {
			if (j > 3) {
				String tem = s.substring(j - 4, j);
				a[i] = Integer.parseInt(tem);
			} else {
				String tem = s.substring(0, j);
				a[i] = Integer.parseInt(tem);
			}
		}
		return a;
	}

	public void out() {
		for (int i = 0; i < 4; i++)
			if (c[i] != 0)
				System.out.print(c[i]);
		System.out.println();
	}

	public int addcheck(int a, int b) {
		int flag;
		if (a + b > 10000)     //由於規定了是一個4位數故大於10000就是進位了
			flag = 1;
		else
			flag = 0;
		return flag;
	}

	public void add() {
		int flag = 0;           //flag爲進位
		for (int i = 3; i >= 0; i--) {
			int d = addcheck(a[i], b[i]);
			c[i] = a[i] + b[i] - d * 10000 + flag;
			flag = d;
		}
		out();
	}

	public int subcheck(int a, int b) {
		if (a - b < 0)
			return -1;
		return 0;
	}

	public void sub() {
		int flag = 0;
		boolean temp = true;
		//考慮到有可能b存放到數比a大先檢測如果是b大那麼將a b互換後在進行減法用temp記錄正負
		for (int i = 0; i < 4; i++) {
			if (a[i] != 0 && b[i] == 0) {
				break;
			}
			if (a[i] < b[i]) {
				c = a;
				a = b;
				b = c;
				temp = false;
				break;
			}
		}
		for (int i = 3; i >= 0; i--) {
			int d = subcheck(a[i], b[i]);
//			System.out.println(a[i] + " " + b[i]);
			c[i] = (-d) * 10000 + a[i] - b[i] + flag;
//			System.out.println(c[i]);
			flag = d;
		}
		System.out.print(temp ? "" : "-");
		out();
	}

	public int[] mulpre(int a,int b){
		int flag=10000;
		int tempa[]={0,0};
		int tempb;
		for(int i=1;i<5;i++){
			tempb=b%10;
//			System.out.println(tempb);
			b=b/10;
			tempa[0]+=a*tempb/flag;
//			System.out.println(tempa[0]);
			tempa[1]+=a*tempb%flag*(10000/flag);
			flag/=10;
		}
		tempa[0]+=tempa[1]/10000;
		tempa[1]%=10000;
		return tempa;
	}

	public void mul(){
		int flag;
		int[] temp1=mulpre(a[3], b[3]);
		int[] temp2=mulpre(a[2], b[2]);
		int[] temp3=mulpre(a[3], b[2]);
		int[] temp4=mulpre(a[2], b[3]);
		c[3]=temp1[1];
		c[2]=temp1[0]+temp3[1]+temp4[1];
		flag=c[2]/10000;
		c[2]=c[2]%10000;
		c[1]=temp3[0]+temp4[0]+temp2[1]+flag;
		flag=c[1]/10000;
		c[1]=c[1]%10000;
		c[0]=temp2[0];
		out();
	}
	public void div(int div){
		int flag=0;
		for(int i=0;i<4;i++){
			a[i]+=flag*10000;
			c[i]=a[i]/div;
			flag=a[i]%div;
		}
		out();
	}
	
	public static void main(String[] args) {
		BigInteger bi = new BigInteger("1076234", "92343241");
		bi.add();
		bi.sub();
		bi.mul();
		bi.div(2);
	}

}
這是在這兒的第一篇,有什麼表達不清楚的可以找我哈,有什麼錯誤的也請多多包涵。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章