D3.高精度

1.分类情况

A+B、A-B、A*a、A/b

A和B指的是超大超长整数,长度<=1e6;

a的值<=10000;

2.大整数的存储

int 变量肯定是存不了这么大的数的,做法是将大整数先存到string字符串,再使用字符串的访问方式,将每一位数存到数组中。

  • 因为加减涉及到数字的进位问题,要在数组最后加一个数是简单的,但是要算在数组第一个下标处进一位是麻烦的

3.运算

模拟人工加法的过程,每次计算Ai+Bi+t(t是上一次的进位,0或1)

高精度加法
  • 模板:
cpp 复制代码
vector<int> add(vector<int> &A, vector<int> &B)
{
    vector<int> C;
    int t = 0;
    for(int i = 0; i < A.size() || i < B.size(); i ++)
    {
        if(i < A.size()) t += A[i];
        if(i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }
    if(t) C.push_back(1);
    return C;
}
add(A,B);

注意在调用的时候和定义函数不同,直接传入就行,不用取址符号------引用

  • main函数中将字符串转化为数字
cpp 复制代码
	string a;//"12345"
    cin >> a;
    for(int i = a.size()-1; i >= 0; i --)
        A.push_back(a[i] - '0');//{5,4,3,2,1}

运算时还是根据ASCII表的数值,可以看到数组的字符形式的十进制和整形数字相差了一个字符 '0'.

高精度减法
cpp 复制代码
bool cmp(vector<int> &A, vector<int> &B)//判断是否有A>=B
{
    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()) t -= B[i];
        if(t >= 0)
        {
            C.push_back(t);
            t = 0;
        }
        else
        {
            C.push_back((t + 10) % 10);
            t = 1;
        }
    }
    
    //除去前导0
    while(C.size() > 1 && C.back() == 0)
        C.pop_back();
    return C;
}
高精度x低精度

高精度乘法的算法和人计算乘法时的过程稍有不同。Axb,A很长,使用string来储存,b很短,使用int即可。

将b看成一个整体去乘,而不是一位一位去乘。

cpp 复制代码
vector<int> mul(vector<int> &A, int b)
{
    vector<int> C;
    int t = 0;
    for(int i = 0; i < A.size(); i ++)
    {
        t = t + A[i] * b;
        C.push_back(t % 10);
        t = t / 10;
    }
    
    //处理最后的进位
    while(t)
    {
        C.push_back(t % 10);
        t = t / 10;
    }
    
    return C;
}
//注意在main函数中考虑b=0的情况,否则输出0000而不是0
if(b)
    C = mul(A,b);
else 
    C.push_back(0);
高精度 / 低精度

模板

cpp 复制代码
vector<int> div(vector<int> &A, int b, int &x)
{
    vector<int> C;
    int r = 0;
    for(int i = A.size() - 1; i >= 0; i --)
    {
        r = r * 10 + A[i];
        C.push_back(r / b);
        r = r % b;
    }
    x = r;
    reverse(C.begin(),C.end());
    
    while(C.size() > 1 && C.back() == 0)
        C.pop_back();
    return C;
}

注意除法是从A[]的高位开始除起,答案也是从高位开始存到C[]中。为了保证加减乘除格式的统一性,所以要在完成之后reverse(C.begin(),C.end());反转一下保证储存顺序,当然在输出的时候也是反着输出,注意会出现前导0的情况出现。

在加减乘除算法中,减法和除法 会出现前导零的情况;乘法会有特殊b = 0的存在.

4.刷题

对于未知的多组数据使用while(cin >> a >> b)每次循环的时候要清空vector数组!

对于已知的多组数据使用cin >> n;while(n --),同样在必要时每次循环清空数组,重新输入!

题外
  1. 表示2的i次方:1 << i 或者 #include<cmath> pow(2,i) 而不是2 ^ i.在 C++ 中,^ 是按位异或运算符.

  2. 注意字符串使用双引号" ",char类型使用单引号' '

  3. int 最多9位数;long long最多18位数

  4. 专门用于输出字符串的函数puts("No!");,并且它会自动在字符串末尾添加换行符。

cpp 复制代码
if (CC == A) puts("Yes");  
else puts("No");

==运算符可以比较两个vector是否相等。如果两个vector的大小相等,并且所有对应位置的元素都相等,那么这两个vector相等。

相关推荐
众少成多积小致巨21 分钟前
libbinder_ndk 入门指南
前端·c++·架构
历程里程碑31 分钟前
二叉树---翻转二叉树
开发语言·c++·elasticsearch·链表·搜索引擎·tornado·dash
B325帅猫-量子前沿技术研究所32 分钟前
PSD和FFT的关系
人工智能·算法
闻缺陷则喜何志丹34 分钟前
【排序】P6149 [USACO20FEB] Triangles S|普及+
c++·算法·排序·洛谷
avocado_green40 分钟前
【LeetCode】90. 子集 II
算法·leetcode
tankeven1 小时前
HJ178 【模板】双指针
c++·算法
君义_noip1 小时前
信息学奥赛一本通 4131:【GESP2506六级】学习小组 | 洛谷 P13015 [GESP202506 六级] 学习小组
算法·动态规划·gesp·信息学奥赛
charlie1145141911 小时前
嵌入式C++工程实践——第13篇:第一次重构 —— enum class取代宏,类型安全的开始
开发语言·c++·vscode·stm32·安全·重构·现代c++
CHANG_THE_WORLD1 小时前
C++ 文件读取函数完全指南
开发语言·c++
6Hzlia1 小时前
【Hot 100 刷题计划】 LeetCode 300. 最长递增子序列 | C++ 动态规划 & 贪心二分
c++·leetcode·动态规划