大数--高精度运算【C语言】

大数–高精度运算【C语言】

鸽了这么多天,今天来学学ACM的入门知识
高精度–也就是数字位数太多需要我们自己定义来表示

我们可以直接用数组,
或者将值和数的长度封装成结构体来表示

#include<stdio.h>
#include<string.h>
#define MAXN 100000 

typedef struct BigNum{
	int len,val[MAXN];
} BigNum;

那我们知道大数不能和其他数据类型一样简单的用scanf,printf输入输出
所以需要自己定义

//大数存储
int string2num(char str[],int num[]){
	int length = strlen(str);
	for(int i = 0;i < length;i++){
		num[i] = str[length - 1 - i] - '0';
	}
	return length;
} 
//大数输出
void output(int num[],int length){
	for(int i = length - 1;i >= 0;i--){
		printf("%d",num[i]);
	}
} 

除了一位一位储存,也可以压位储存
请小伙伴尽情百度

下面说说大数运算

首先是大数的加法
可以手动模拟来寻找思路,
重点需要用carry来表示进位

int Add(int a[],int length_a,int b[],int length_b,int c[]){
	int length_c,mod = 10,carry = 0,sum = 0;
	length_c = length_a > length_b ? length_a:length_b;
	for(int i = 0;i < length_c;i++){
		sum = a[i] + b[i] + carry;
		c[i] = sum % mod;
		carry = sum / mod;
	}
	if(carry != 0) c[length_c++] = carry;
	return length_c;
}

下面是结构体形式的源码

BigNum Add(BigNum A,BigNum B){
	int mod = 10,carry = 0,sum = 0;
	BigNum C;
	C.len = A.len > B.len ? A.len : B.len;
	for(int i = 0;i < C.len;i++){
		sum = A.val[i] + B.val[i] + carry;
		C.val[i] = sum % mod;
		carry = sum / mod;
	}
	if(carry != 0) C.val[C.len++] = carry;
	return C;
}

大数的减法
重点在于借位,同时也要注意0的处理

BigNum minus(BigNum A,BigNum B){
	int mod = 10,borrow = 0,diff = 0;
	BigNum C;
	C.len = A.len > B.len ? A.len : B.len;
	for(int i = 0;i < C.len;i++){
		diff = A.val[i] - B.val[i] - borrow;
		C.val[i] = diff % mod;
		borrow = diff < 0? 1 : 0;
	}
	while(C.val[C.len - 1] == 0 && C.len > 1) C.len --;
	return C;
}

大数的乘法
多位*一位与加法类似

//多位*一位
int multi(int a[],int len_a,int b,int c[]){
	int rslt = 0,mod = 10,carry = 0;
	int len_c = len_a;
	for(int i = 0;i < len_c;i++){
		rslt = a[i] * b + carry;
		c[i] = rslt % mod;
		carry = rslt / mod;
	}
	if(carry != 0) c[len_c ++] = carry;
	return len_c;
}

多位 * 多位转化成多位 * 一位来做

int multi(int a[],int len_a,int b,int len_b,int c[]){
	int sum = 0,mod = 10,carry = 0;
	int len_c = len_a + len_b;
	memset(c,0,len_c);
	for(int j = 0;j < len_b;j++){
		for(int i = 0;i < len_a;i++){
			sum = c[i+j] + a[i] * a[b] +carry;
			c[i+j] = sum % mod;
			carry = sum / mod; 
		}
	}
	while(len_c == 0 && len_c > 0) len_c -- ;
	return len_c;
}

最后是大数除法
注意要记录余数
举个多位 / 一位的栗子

//高精度除以低精度
BigNum divide(BigNum A,int b,int &rest){
	int ans = 0,mod = 10;
	BigNum C;
	C.len = A.len;
	memset(C.val, 0, C.len); 
	rest = 0;
	for(int i = A.len - 1;i >= 0;i--){
		ans = rest * mod + A.val[i]; 
		C.val[i] = ans / b;
		rest = ans % b;
	}
	while(C.val[C.len--] == 0 &&C.len > 0) C.len -- ;
	return C;
} 

多位 / 多位留给大家自己写啦
因为我还没写,没法分享源码了

多说一下
在运算类似 35654611365646486 +(-54487816151311531531315)这种时
需要自己用sig来记录数的正负,进而转换到上述运算中去。

明天见~

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值