1:大整数加法
#include <iostream>
#include <string.h>//用memset的头文件
#include <string>//用string的头文件;oj上好像不加这个也行
//c++的输入输出
//https://blog.csdn.net/qq_40725780/article/details/81032700
using namespace std;
#define MAX 200
unsigned int num[MAX + 10];
unsigned int num1[MAX + 10];
int main()
{
string str1, str2;
cin >> str1 >> str2;
memset(num, 0, sizeof(num));
memset(num1, 0, sizeof(num1));
int len = str1.length(); int index = 0;
for (int i = len - 1; i >= 0; i--)
{
num[index++] = str1[i] - '0';
}
len = str2.length(); index = 0;
for (int i = len - 1; i >= 0; i--)
{
num1[index++] = str2[i] - '0';
}
len = str1.length() > str2.length() ? str1.length() : str2.length();
for (int i = 0; i < len; i++)
{
num[i] += num1[i];
if (num[i] >= 10)
{
num[i] -= 10;
num[i + 1]++;
}
}
bool flag = false;//去0操作
for (int i = len; i >= 0; i--)
{
if (flag || num[i])
{
flag = true;
cout << num[i];
}
}
if (!flag)
{
cout << "0";
}
return 0;
}
- 大数除法
//基本的思想是反复做减法,看看从被除数里昀多能减去多少个除数,商就是多少。
//一个一个减显然太慢,如何减得更快一些呢?以 7546除以 23为例来看一下:
//开始商为 0。先减去 23的 100倍,就是 2300,发现够减 3次,余下 646。
//于是商的值就增加 300。然后用 646减去 230,发现够减 2次,余下 186,
//于是商的值增加 20。昀后用 186减去 23,够减 8次,因此昀终商就是 328
//思路:所以本题的核心是要写一个大整数的减法函数,然后反复调用该函数进行减法操作。
//计算除数的 10倍、100倍的时候,不用做乘法,直接在除数后面补 0即可。
//https://blog.csdn.net/justidle/article/details/104431257/采用数组实现
#include <iostream>
#include <string.h>
#define MAX_LEN 200
char szLine1[MAX_LEN + 10];
char szLine2[MAX_LEN + 10];
int an1[MAX_LEN + 10]; //被除数, an1[0]对应于个位
int an2[MAX_LEN + 10]; //除数, an2[0]对应于个位
int aResult[MAX_LEN + 10]; //存放商, aResult[0]对应于个位
/* Substract函数:长度为 nLen1的大整数 p1减去长度为 nLen2的大整数 p2
减的结果放在 p1里,返回值代表结果的长度
如不够减返回-1,正好减完返回 0
p1[0]、p2[0]是个位 */
int Substract(int * p1, int * p2, int nLen1, int nLen2)
{
int i;
if (nLen1 < nLen2)
return -1;
//下面判断 p1是否比 p2大,如果不是,返回-1
bool bLarger = false;
if (nLen1 == nLen2) {
for (i = nLen1 - 1; i >= 0; i--) {
if (p1[i] > p2[i])
bLarger = true;
else if (p1[i] < p2[i]) {
if (!bLarger)
return -1;
}
}
}
for (i = 0; i < nLen1; i++) { //做减法
p1[i] -= p2[i]; //要求调用本函数时给的参数能确保当 i>=nLen2时,p2[i] = 0
if (p1[i] < 0) {
p1[i] += 10;
p1[i + 1] --;
}
}
for (i = nLen1 - 1; i >= 0; i--)
if (p1[i])
return i + 1;
return 0;
}
int main()
{
int t, n;
char szBlank[20];
scanf("%d", &n);
for (t = 0; t < n; t++) {
scanf("%s", szLine1);
scanf("%s", szLine2);
int i, j;
int nLen1 = strlen(szLine1);
memset(an1, 0, sizeof(an1));
memset(an2, 0, sizeof(an2));
memset(aResult, 0, sizeof(aResult));
j = 0;
for (i = nLen1 - 1; i >= 0; i--)
an1[j++] = szLine1[i] - '0';
int nLen2 = strlen(szLine2);
j = 0;
for (i = nLen2 - 1; i >= 0; i--)
an2[j++] = szLine2[i] - '0';
if (nLen1 < nLen2) {
printf("0\n");
continue;
}
nLen1 = Substract(an1, an2, nLen1, nLen2);
if (nLen1 < 0) {
printf("0\n");
continue;
}
else if (nLen1 == 0) {
printf("1\n");
continue;
}
aResult[0] ++; //减掉一次了,商加 1
//减去一次后的结果长度是 nLen1
int nTimes = nLen1 - nLen2;
if (nTimes < 0) //减一次后就不能再减了
goto OutputResult;
else if (nTimes > 0) {//对齐操作
//将 an2 乘以 10的某次幂,使得结果长度和 an1相同
for (i = nLen1 - 1; i >= 0; i--) {
if (i >= nTimes)
an2[i] = an2[i - nTimes];
else
an2[i] = 0;
}
}
nLen2 = nLen1;
for (j = 0; j <= nTimes; j++) {
int nTmp;
//一直减到不够减为止
//先减去若干个 an2×(10 的 nTimes 次方),
//不够减了,再减去若干个 an2×(10 的 nTimes-1 次方),......
while ((nTmp = Substract(an1, an2 + j, nLen1, nLen2 - j)) >= 0) {
//nTmp代表这次相减之后的返回值的长度:相当于把高位给去掉了
nLen1 = nTmp;
aResult[nTimes - j]++; //每成功减一次,则将商的相应位加 1
}
}
OutputResult:
//下面的循环统一处理进位问题
for (i = 0; i < MAX_LEN; i++) {
if (aResult[i] >= 10) {
aResult[i + 1] += aResult[i] / 10;
aResult[i] %= 10;
}
}
//下面输出结果
bool bStartOutput = false;
for (i = MAX_LEN; i >= 0; i--)
if (bStartOutput)
printf("%d", aResult[i]);
else if (aResult[i]) {
printf("%d", aResult[i]);
bStartOutput = true;
}
if (!bStartOutput)
printf("0\n");
printf("\n");
}
system("pause");
return 0;
}
- 算法笔记中关于大数运算的内容
// 大整数运算.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//1:存储:
#include <iostream>
#include<cstdio>
#include<cstring>
char a[1024];
char b[1024];
//1:存储:整数的最高位存储到数组的最高位,字符串进行读入时需要进行反转
struct bign {
int d[1024];
int length;
bign() { //结构体初始化
memset(d, 0, sizeof(d));
length = 0;
}
};
bign change(char str[]) {
bign a;
a.length = strlen(str);
for (int i = 0; i < a.length; i++)a.d[i] = str[a.length - 1 - i] - '0';
/*int j = 0;用两个指针的方法进行扫描就不用计算i
for (int i = a.length - 1; i >= 0; i--)
{
a.d[j++] = str[i]-'0';
}*/
return a;
}
//2:大整数的加法
bign add(bign a, bign b)
{
bign c;
int carry=0;//carry是进位
for (int i = 0; i < a.length || i < b.length; i++)//以较长的为界限
{
int temp = a.d[i] + b.d[i] + carry;
c.d[c.length++] = temp %10;
carry = temp / 10;
}
if (carry)c.d[c.length++] = carry;//最后一位进位不为0,则直接复制给结果的最高位
while (c.length-1>=1&&a.d[c.length-1]==0)
{
c.length--;
}
return c;
}
//3:高精度减法
//3.1判断数的大小;是否能减;
//3.2进行去重
int compare(bign a, bign b)
{
if (a.length > b.length)return 1;
else if (a.length < b.length)return - 1;
else {
for (int i = a.length - 1; i >= 0; i--) {
if (a.d[i] > b.d[i])return 1;
else if (a.d[i] < b.d[i])return -1;
}
return 0;
}
}
bign sub(bign a, bign b)
{
bign c;
for (int i = 0; i < a.length || i<b.length; i++)//以较长的为界限
{
if (a.d[i] < b.d[i])
{
//注意这里不能用i++
a.d[i + 1]--;
a.d[i] += 10;
}
c.d[i] = a.d[i] - b.d[i];
}
while (c.length>1&&c.d[c.length-1]==0)
{
c.length--;
}
return c;
}
//4:高精度乘法:大数和整数相乘
//4.1步骤:把整数看做一个整体,和大数的每一位相乘再与进位相加,所得的结果的个位数作为该位的结果
//高的部分作为进位
//4.2:如果存在负号,则需要先记下负号,然后取绝对值进行代入
bign multi(bign a, int b)
{
bign c; int carry = 0;
for (int i = 0; i < a.length; i++)//以较长的为界限
{
int temp = a.d[i] * b + carry;
c.d[c.length++] = temp % 10;
temp /= 10;
}
while (carry)
{
c.d[c.length++] = carry % 10;
carry /= 10;
}
return c;
}
//5:大整数除法
//5.1:上一步的余数*10+该步的位,得到该步临时的被除数,和除数进行对比,如果不够除,则商为0;否则商即为对应的商,余数就是对应的余数
//5.2:进行去0
bign divide(bign a, int b,int &r)//如果多个地方用到,就可以直接对原变量进行修改
{
bign c;
c.length = a.length;//被除数和商的每一位都是一一对应的,所以先令其相等
for (int i = a.length; i >=0; i++)//从高位开始
{
r = r * 10 + a.d[i];//和上一位遗留的余数进行结合
if(r<b)c.d[i]=0;
else {
c.d[i] = r / b;
r %= b;
}
}
while (c.length > 1 && c.d[c.length - 1] == 0)
{
c.length--;
}
return c;
}
void print(bign a) {
for (int i = a.length - 1; i >= 0; i--)
{
printf("%d", a.d[i]);
}
/* prin
tf("\n");*/
}
int main()
{
scanf("%s", a);
scanf("%s", b);
bign n = change(a);
bign m = change(b);
print(add(n, m));
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件