大整数运算---模拟笔算

/*
*m=a[k]×10k-1+a[k-1]×10k-2+….+a[2]×10+a[1]
*其中a[0]保存该长整数的位数。
*
*模拟笔算
*/
#include<iostream>
#include<cstring>
using namespace std;
#define SIZE 255

void getl(char* n);//获取长整数
void prt(char* n);//打印长整数
int cmp(char* n1, char* n2);//比较长整数大小
void swap(char * n);//长整数位交换
void cpy(char* n1, char* n2);//复制长整数
/**********************************************/
//乘法
void mul(char* n1, char* n2);
void muld(char* n, int t, char num);//位乘
/**********************************************/
//除法
void div(char* n1, char* n2, char* q);
/**********************************************/
//加法
void plu(char* n1, char* n2);
int plua(char* n, int off, char num);//位加
/**********************************************/
//减法
int sub(char* n1, char* n2);//返回0正1负
int suba(char* n1, int off, char num);//位减
/**********************************************/

int main(int argc, char** argv){
	cout<<"长整数乘除法运算。"<<endl<<endl;
	while(1){
		cout<<"请选择运算: 1.乘法; 2.除法。"<<endl;
		int t;
		//t=2;
		cin>>t;
		if(t == 1){
			cout<<"请依次输入 被乘数、乘数。"<<endl;
		}else if(t == 2){
			cout<<"请依次输入 被除数、除数。"<<endl;
		}else{
			cout<<"输入错误,请重试。";
			continue;
		}
		fflush(stdin);
		char n1[SIZE]={0},n2[SIZE]={0};
		getl(n1);
		getl(n2);
		if(t == 1){
			mul(n1, n2);
			cout<<"结果:";
			prt(n1);
		}
		else{
            char q[SIZE] = {0};
			if(n2[0]==1 && n2[1]==0){
				cout<<"输入错误:除数不能为0"<<endl;
				continue;
			}
            div(n1, n2, q);
            cout<<"商:";
			prt(n1);
			cout<<"余数:";
            prt(q);
		}
	}
	return 0;
}
/**********************************************/
void getl(char* n){
	//从console获取一个长整数
	char tmp;
	while(tmp = getchar()){
		if(tmp <= '9'&&tmp >= '0'){
			break;
		}
	}
	int i=1;
	while(tmp <= '9'&&tmp >= '0'){
		n[i] = tmp;
		n[i] -= '0';
		tmp = getchar();
		i++;
	}
	n[0] = i-1;
	swap(n);
}
void prt(char* n){
    //打印一个大整数
	if(n[0] == 0){
		cout<<"0";
	}
    for(int i=n[0];i >= 1; i--){
        cout<<char(n[i] + '0');
    }
    cout<<endl;
}
int cmp(char* n1, char* n2){
    //比较两个大整数的大小 n1>n2返回1
    if(n1[0] > n2[0]){
        return 1;
    }else if(n1[0] < n2[0]){
        return -1;
    }else{
        for(int i=n1[0]; i>=1; i--){
            if(n1[i] == n2[i]){
                continue;
            }else{
                if(n1[i] > n2[i]){
                    return 1;
                }else{
                    return -1;
                }
            }
        }
    }
    return 0;
}
void swap(char* n){
	//按脚码逆置一个大整数
	char tmp;
	for(int i=1; i<=n[0]/2; i++){
		tmp = n[i];
		n[i] = n[n[0] - i + 1];
		n[n[0] - i + 1] = tmp;
	}
}
void cpy(char* n1, char* n2){
	//将n1复制为n2
	for(int i=0; i<=n2[0]; i++){
		n1[i] = n2[i];
	}
}
/**********************************************/
void mul(char* n1, char* n2){
	//乘法,结果保存在n1
	char result[SIZE] = {0};
	char tmp[SIZE] = {0};
	for(int i=1; i<=n2[0]; i++){
		cpy(tmp, n1);
		muld(tmp, i - 1, n2[i]);
		plu(result, tmp);
	}
	cpy(n1, result);
}
void muld(char* n, int t, char num){
	//个位数乘,将n乘以 后跟t个零的个位数num,完成进位
	char k = 0;//进位数
	int i;
	for(i = 1; i<=n[0]; i++){
		n[i] *= num;
		n[i] += k;
		if(n[i] > 9){
			k = n[i]/10;
			n[i] %= 10;
		}else{
			k = 0;
		}
	}
	if(k){
		n[0]++;
		n[i] = k;
	}
	//左移
	for(int i=n[0]; i>=1; i--){
		n[i+t] = n[i];
	}
	for(int i=1; i<=t; i++){
		n[i] = 0;
	}
	n[0] += t;
}
/*
*已废弃
int mula(char* n, int off, char num){
	//位乘,将n偏移为off的地方乘上num,返回进位
	n[off] *= num;
	cout<<"off "<<off<<endl;
	logi("n[off] ",n[off]%10);
	logi("num ",num);
	if(n[off] > 9){
		n[off] %= 10;
		return n[off]/10;
	}else{
		return 0;
	}
}
void mulplu(char* n, int off, char num){
	//乘法中用到的加法,将n偏移为off的位加上num,完成进位,结果保存在n
	int i;
	char k = n[off];
	for(i=off; k||i==off; i++){
		k = plua(n, i, k);
	}
	//i:最前面的不是进位的偏移
	if(i-2 > n[0]){
		n[0] = i-2;
	}
}
*/
/**********************************************/
/*
从n1最高位开始
余数=0
while(可以向右截取){
    余数 加上向右取的
    while(取得的数小于n2){
        向右取
    }
    while(余数 >= n2){
        商++
        余数 -= n2
    }
	商放在结果的 截取位的最右位
	余数乘以10
}
*/
void div(char* n1, char* n2, char* q){
	//除法,商保存在n1,余数保存在q
	char remd[SIZE] = {0};//余数
    char ans[SIZE] = {0};//结果
    char d[SIZE] = {0};//截取的一位数
	d[0] = 1;
	char ten[SIZE] = {0};//长整数10
	ten[0] = 2;
	ten[1] = 0;
	ten[2] = 1;
	//保存未乘10的个位余数
	char tn[SIZE] = {0};
	bool over = false;
    int w = n1[0];//截取位
	while(w != 0){
		d[1] = n1[w];
		plu(remd, d);
		while(cmp(remd, n2) == -1){
			//乘10之前保存个位余数
			if(w == 1){
				cpy(tn, remd);
			}
			mul(remd, ten);
			w--;
			//向右取之前确定可以取
			if(w == 0){
				over = true;
				break;
			}
			d[1] = n1[w];
			plu(remd, d);
		}
		if(over){
			break;
		}
		char qu = 0;//商
		while(cmp(remd, n2) != -1){
			qu++;
			sub(remd, n2);
		}
		//加在结果的当前截取到位
		plua(ans, w, qu);
		//乘10之前保存个位余数
		if(w == 1){
			cpy(tn, remd);
		}
		mul(remd, ten);
		w--;
	}
	cpy(remd, tn);
	//计算ans的位数
    for(int i=n1[0]; i>=1; i--){
        if(ans[i] != 0){
            ans[0] = i;
            break;
        }
    }
    cpy(n1, ans);
    cpy(q, remd);
}
/**********************************************/
void plu(char* n1, char* n2){
	//加法,结果保存在n1
	int i;
	int k = 0;
	int maxlen = n1[0]>n2[0]?n1[0]:n2[0];
	for(i=1; i<=maxlen; i++){
		k = plua(n1, i, n2[i] + k);
	}
	n1[0] = maxlen;
	if(k){
		n1[0]++;
		n1[i] = k;
	}
}
int plua(char* n, int off, char num){
	//位加法,将n偏移为off的地方加上num,返回进位
	n[off] += num;
	if(n[off] > 9){
		int t = n[off]/10;
		n[off] %= 10;
		return t;
	}else{
		return 0;
	}
}
/**********************************************/
int sub(char* n1, char* n2){
    //减法,n1:被减数 n2:减数 n1>=n2 结果放在n1 返回1负数0正数
    int foo;
    char t[SIZE] = {0};
    if((foo = cmp(n1, n2)) == -1){
        cpy(t, n2);
        cpy(n2, n1);
        cpy(n1, t);
    }
    char w = 0;//借位数
    int i=1;
    for(;i<=n2[0]; i++){
        w = suba(n1, i, n2[i] + w);
    }
    while(w){
        w = suba(n1, i, n2[i] + w);
        i++;
    }
    //清除无效0
    for(int k=n1[0]; k>=1; k--){
        if(n1[k] == 0){
            n1[0]--;
        }else{
            break;
        }
    }
    if(foo == -1){
        //复原n2
        cpy(n2, t);
        return 1;
    }else{
        return 0;
    }
}
int suba(char* n, int off, char num){
	//位减法,将n偏移为off的地方减去num,返回借位
    n[off] -= num;
    if(n[off] < 0){
        n[off] += 10;
        return 1;
    }else{
        return 0;
    }
}
/**********************************************/

时间: 2024-10-13 16:16:57

大整数运算---模拟笔算的相关文章

大整数运算

对于A,B的范围在int范围内,求解A与B的加减乘除运算我相信大家很快就可以写出程序来,但是如果A,B是有着1000个数位的整数呢?恐怕就没有已有的数据类型来表示了,这时候只能老实的模拟加减乘除运算的过程.模拟加减乘除的运算的过程,原理就是小学的. 大整数又称为高精度整数,其含义就是用基本的数据类型无法存储其精度的整数.大整数运算即高精度运算. 首先,介绍大整数的存储. 很简单,用数组即可.例如,int型数组d[1000]:如将123456存储到数组中,则有d[0]=6,d[1]=5......

大整数运算模板总结

大整数运算模板总结. 大整数结构体表示 整型数组从低位到高位顺序存储每一位数字,另外需要存储数字的长度. struct bign { int d[1000]; int len; bign(){ memset(d, 0, sizeof(d)); len = 0; } }; 大整数输入 一般通过字符串输入. bign Change(string str)//输入字符串转大整数 { bign a; a.len = str.length(); for (int i = 0; i < a.len; i++

算法学习——大整数运算(高精度)C++

1.大整数加法 用数组来存储大整数的每一位,然后模拟人工运算,用for循环按位运算和处理,原理十分简单,直接上模板. #include<iostream> #include<vector> using namespace std; //大整数加法 vector<int> add(vector<int>& A,vector<int>& B){ vector<int> C; int t = 0; for(int i = 0

大整数运算C++1

//下面的代码勉强算是bignum_beta1版本! //实现了大整数的加减乘除四则运算,以及求两个整数的最大公约数,以及求乘法逆,miller_rabin素性检验,平方_乘法算法 //不足之处,位数还很难扩展至几千位,以及运算速度有一点慢,既然是beta1,说明bug还是挺多的 //程序缺少测试数据来测试,所以有的结果不敢保证其正确性 //由于使用c++复写了很多运算符,加入这个文件之后,大数bignum可以看做是一个如同如同int一样的基本类型 //可以像int一样加减乘除和输入输出 #in

大整数运算C++

//下面的代码勉强算是bignum_beta1版本! //实现了大整数的加减乘除四则运算,以及求两个整数的最大公约数,以及求乘法逆,miller_rabin素性检验,平方_乘法算法 //不足之处,位数还很难扩展至几千位,以及运算速度有一点慢,既然是beta1,说明bug还是挺多的 //程序缺少测试数据来测试,所以有的结果不敢保证其正确性 //由于使用c++复写了很多运算符,加入这个文件之后,大数bignum可以看做是一个如同如同int一样的基本类型 //可以像int一样加减乘除和输入输出 #in

基于Java的大整数运算的实现(加法,减法,乘法)学习笔记

大整数,顾名思义就是特别大的整数. 一台64位的机器最大能表示的数字是2的64次方减一: 18446744073709551615 java语言中所能表示的整数(int)最小为-2147483648 public class test { public static void main(String[] args) { System.out.println(Integer.MIN_VALUE); } } 最大为 2147483647 public class test { public stat

算法___大整数运算

1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <string> 5 #include <stdlib.h> 6 #include <algorithm> 7 using namespace std; 8 string MULTIPLY_INT(string str1 , string str2); 9 string MINUS_I

大整数运算 ——第一次个人项目报告

1.          首先在输入上,除了考虑第一位正负号和起始0的情况外,还考虑了每行仅仅只有一个换行符的情况.防止在多组输入情况下,误输入4行数据. 2.          在加法运算中,主要分类讨论了两个运算符的加减情况,直接先判断结果的正负情况,再判断是加法还是减法,减法运算仅仅是改变了第二个运算符的正负情况,特别判断了一下运算符是0和结果是0的输出情况,运算才用手工模拟. 3.          乘法采用了FFT的算法,将在时域上复杂度为O(n^2)的卷积运算,变成了频域上简单的相乘,

大整数运算练习

#include<stdio.h> #include<string.h> struct bign { int d[1000]; int len; bign() { //构造函数(函数名和结构体相同, 无返回值) memset(d, 0, sizeof(d)); //头文件<string.h> len = 0; } }; bign change(char str[]) { //字符串倒着赋给d[]数组 bign a; a.len = strlen(str); for (i