高精度

定位

Java和Python不用;
高精度在面试中不常考,但是在笔试容易出;
加减要求位数在1e6;
乘法大的那个数位数要小于1e6,小的数要小于1e9或1万;
除法和大乘大就有点变态了;

高精度加法

本质上就是人类使用的加法用计算机表示,每个数字用数组存储

#include<iostream>
#include<vector>
using namespace std;
const int N = 1e6 + 10;//额外+10防止出现边界问题
int arr[N] = { 0 };

vector<int>add(vector<int>& A, vector<int>& B)//用数组来表示的整数A与B,返回的和也用数组表示;
{
	vector<int>C;//C为和;

	int t = 0;//t为进位;
	for (int i = 0; i < A.size() || i < B.size(); i++)
	{
		if (i < A.size())//如果A在该位有值
		{
			t += A[i];//t+A在该位的值
		}
		if (i < B.size())//如果B在该位有值
		{
			t += B[i];//t+B在该位的值
		}
		C.push_back(t % 10);//得到这一位的和;
		t /= 10;//是否需要进位;
	}
	if (t)//如果t在第一位进位了
	{
		C.push_back(1);//则下一位补上一个1;
	}
	return C;
}

int main()
{
	string a, b;
	vector<int>A, B;

	cin >> a >> b;//若a为123456
	for (int i = a.size() - 1; i >= 0; i--)
	{
		A.push_back(a[i] - '0');//存储数字,因为a[i]为一个字符数字,要把它转换为数字需要对一个数字进行运算,a对应的A为{6,5,4,3,2,1}
	}
	for (int i = b.size() - 1; i >= 0; i--)//同理
	{
		B.push_back(b[i] - '0');
	}

	auto C = add(A, B);

	for (int i = C.size() - 1; i >= 0; i--)
	{
		printf("%d", C[i]);//从数组高位往数组低位打印,得到从个位到最高位的数;
	}

	return 0;
}

高精度减法

1)判断结果正负;
2)借位;

bool cmp(vector<int>& A, vector<int>& B)//这里不能用strcmp,它无法比较位数;
{
	if (A.size() != B. size())
	{
		return A.size() > B.size();
	}
	for (int i = A.size() - 1; i >= 0; i--)
	{
		if (A[i] != B[i])
		{
			return A[i] > B[i];
		}
	}
	return true;
}

vector<int>sub(vector<int>& A, vector<int>& B)
{
	vector<int>C;
	int t = 0;
	for (int i = 0; i < A.size(); i++)//主函数里保证了左边的变量大于右边的变量;
	{
		t = A[i] - t;
		if (i < B.size())//判断B在该位是不是存在,如果存在再减去;
		{
			t -= B[i];
		}
		C.push_back((t + 10) % 10);//若t>=0,则(t+10)%10就是t的本身,若t<0,则(t+10)%10就是t借位后的值;
		if (t < 0)
		{
			t = 1;//借位,然后下一位运算会额外减1;
		}
		else
		{
			t = 0;
		}
	}

	while (C.size() > 1 && C.back() == 0)//若位数大于1,且最后一位为0;
	{
		C.pop_back();//去掉最后一位,也就是先导0;eg:120-119=001,该函数就是为了去掉0;
	}

	return C;
}
int main()
{
	string a, b;
	vector<int>A, B;

	cin >> a >> b;//若a为123456
	for (int i = a.size() - 1; i >= 0; i--)
	{
		A.push_back(a[i] - '0');//存储数字,则A为{6,5,4,3,2,1}
	}
	for (int i = b.size() - 1; i >= 0; i--)//同理
	{
		B.push_back(b[i] - '0');
	}

	if (cmp(A, B))//比较A,B的大小,如果A>B;
	{
		auto C = sub(A, B);

		for (int i = C.size() - 1; i >= 0; i--)
		{
			printf("%d", C[i]);//从数组高位往数组低位打印,得到从个位到最高位的数;
		}
	}
	else//如果B>A,则需要输出负数;
	{
		auto C = sub(B, A);
		printf("-");
		for (int i = C.size() - 1; i >= 0; i--)
		{
			printf("%d", C[i]);//从数组高位往数组低位打印,得到从个位到最高位的数;
		}
	}
	return 0;
}

高精度乘法_大乘小

1)每一位的结果都是(Ab+上一位的进位)%10;
2)进的位是(A
b+上一位的进位)/10;
3)大数的每一位都去乘小数(不是小数的每一位);

vector<int>mul(vector<int>& A, int b)
{
	vector<int>C;
	int t = 0;//进位

	for (int i = 0; i < A.size() || t; i++)//要不就是i循环完A,要不就是t被处理完;
	{
		if (i < A.size())
		{
			t += A[i] * b;//如果A还没使用完所有位数;
		}
		C.push_back(t % 10);//每一位的结果都是(A*b+上一位的进位)%10;
		t /= 10;//进的位是(A*b+上一位的进位)/10;
	}
	return C;
}

int main()
{
	string a;
	int b;//高精度a*低精度b;

	cin >> a >> b;

	vector<int>A;
	for (int i = a.size() - 1; i >= 0; i--)
	{
		A.push_back(a[i] - '0');
	}

	auto C = mul(A, b);
        if(b == 0)
        {
                printf("0");
        }
        else
        {
	    for (int i = C.size() - 1; i >= 0; i--)
	    {
		    printf("%d", C[i]);
	    }
        }


	return 0;
}

高精度乘法_高精乘高精

#include<bits/stdc++.h>
using namespace std;
char a[10001], b[10001];
int A[10001], B[10001] ,c[10001];
int i, x, len, j;
int main()
{
	cin >> a >> b;
	int sza = strlen(a);
	int szb = strlen(b);
	for (i = 1; i <= sza; i++)//反向输入,方便乘
	{
		A[i] = a[sza - i] - '0';
	}
	for (i = 1; i <= szb; i++)
	{
		B[i] = b[szb - i] - '0';
	}
	for (i = 1; i <= szb; i++)
        {
		for (j = 1; j <= sza; j++)
                {
			c[i + j - 1] += A[j] * B[i];//错位乘法
                }
        }
	for (i = 1; i < sza + szb; i++)
        {  
		if (c[i] > 9)
		{
			c[i + 1] += c[i] / 10;//进位
			c[i] %= 10;//留下的一位
		}
        }
	len = sza + szb;
	while (c[len] == 0 && len > 1)//去掉前导零
       {
		len--;
	}
	for (i = len; i >= 1; i--)
	{
		cout << c[i];
	}
	return 0;
}

6.C++pow极致优化n次方

#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
	cin >> n;
	cout.precision(0);//删除小数点后的所有的0;
	cout << std::fixed << pow(2.0, n);//将高精算数转化为常规;

	return 0;
}

7.高精除低精

记得去掉前导零。

#include<bits/stdc++.h>
using namespace std;

vector<int>div(vector<int>&A, int b, int &r)//引用余数,可以直接在函数里修改余数;
{
	vector<int>C;//商;
	r = 0;//余数;

	for (int i = A.size() - 1; i >= 0; i--)//除法从最高位开始除,因此存储的也是最高位
	{
		r = r * 10 + A[i];//上一位的余数*10+下一位的数字;
		C.push_back(r / b);//把商放在C的末尾
		r %= b;//得到每一位的余数
	}
	reverse(C.begin(), C.end());//由于从最高位开始存储,因此需要将最高位和最低位之间所有元素全部倒转;
	while (C.size() > 1 && C.back() == 0)
	{
		C.pop_back();
	}
	return C;
}

int main()
{
	string a;
	int b;

	cin >> a >> b;

	vector<int>A;
	for (int i = a.size()-1; i >=0; i--)
	{
		A.push_back(a[i] - '0');
	}

	int r = 0;
	auto C = div(A, b, r);

	for (int i = C.size() - 1; i >= 0; i--)
	{
		printf("%d", C[i]);
	}
	printf("\n");
	printf("%d", r);

	return 0;
}
posted @ 2022-06-21 10:46  Zilliax  阅读(95)  评论(0)    收藏  举报