对于大数字的运算


说明:由于在各种语言中各种整型数据是会受到各种的规范(如在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);
	}

}
这是在这儿的第一篇,有什么表达不清楚的可以找我哈,有什么错误的也请多多包涵。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值