【模板】压位高精度

任何沾染了高精度的题都是恶心的题……
看到高精度的题就烦呐TAT
干脆存一个高精度的模板好了

#include <cstdio>  
#include <cstring>  
#include <algorithm>  


using namespace std;  


const int power = 1;      //每次运算的位数为10的power次方,在这里定义为了方便程序实现  
const int base = 10;      //10的power次方。  


//要压位的时候,只需改power 和 base即可,如压万位高精,那么power = 4, base = 10000  


const int MAXL = 1001;    //数组的长度。  


char a[MAXL], b[MAXL];  
struct num  
{  
    int a[MAXL];  
    num() { memset(a, 0, sizeof(a)); }                      //初始化  
    num(char *s)                                            //将一个字符串初始化为高精度数  
    {  
        memset(a, 0, sizeof(a));  
        int len = strlen(s);  
        a[0] = (len+power-1) / power;                       //数的长度  
        for (int i=0, t=0, w; i < len ;w *= 10, ++i)          
        {  
            if (i % power == 0) { w = 1, ++t; }  
            a[t] += w * (s[i]-'0');  
        }  
        //初始化数组,这里自己模拟一下,应该很容易懂的~  
    }  
    void add(int k) { if (k || a[0]) a[ ++a[0] ] = k; }     //在末尾添加一个数,除法的时候要用到  
    void re() { reverse(a+1, a+a[0]+1); }                   //把数反过来,除法的时候要用到  
    void print()                                            //打印此高精度数  
    {  
        printf("%d", a[ a[0] ]);        
        //先打印最高位,为了压位 或者 该高精度数为0 考虑  
        for (int i = a[0]-1;i > 0;--i)  
        printf("%0*d", power, a[i]);    
        //这里"%0*d", power的意思是,必须输出power位,不够则前面用0补足  
        printf("\n");  
    }  
} p,q,ans;  


bool operator < (const num &p, const num &q)              //判断小于关系,除法的时候有用  
{  
    if (p.a[0] < q.a[0]) return true;  
    if (p.a[0] > q.a[0]) return false;  
    for (int i = p.a[0];i > 0;--i)  
    {  
        if (p.a[i] != q.a[i]) return p.a[i] < q.a[i];  
    }  
    return false;  
}  


num operator + (const num &p, const num &q)               //加法,不用多说了吧,模拟一遍,很容易懂  
{  
    num c;  
    c.a[0] = max(p.a[0], q.a[0]);  
    for (int i = 1;i <= c.a[0];++i)  
    {  
        c.a[i] += p.a[i] + q.a[i];  
        c.a[i+1] += c.a[i] / base;  
        c.a[i] %= base;  
    }  
    if (c.a[ c.a[0]+1 ]) ++c.a[0];  
    return c;  
}  


num operator - (const num &p, const num &q)               //减法,也不用多说,模拟一遍,很容易懂  
{  
    num c = p;  
    for (int i = 1;i <= c.a[0];++i)  
    {  
        c.a[i] -= q.a[i];  
        if (c.a[i] < 0) { c.a[i] += base; --c.a[i+1]; }  
    }  
    while (c.a[0] > 0 && !c.a[ c.a[0] ]) --c.a[0];            
    //我的习惯是如果该数为0,那么他的长度也是0,方便比较大小和在末尾添加数时的判断。  
    return c;  
}  


num operator * (const num &p, const num &q)                   
//乘法,还是模拟一遍。。其实高精度就是模拟人工四则运算!  
{  
    num c;  
    c.a[0] = p.a[0]+q.a[0]-1;  
    for (int i = 1;i <= p.a[0];++i)  
    for (int j = 1;j <= q.a[0];++j)  
    {  
        c.a[i+j-1] += p.a[i]*q.a[j];  
        c.a[i+j] += c.a[i+j-1] / base;  
        c.a[i+j-1] %= base;  
    }  
    if (c.a[ c.a[0]+1 ]) ++c.a[0];  
    return c;  
}  


num operator / (const num &p, const num &q)               //除法,这里我稍微讲解一下  
{  
    num x, y;  
    for (int i = p.a[0];i >= 1;--i)                       //从最高位开始取数  
    {  
        y.add(p.a[i]);             //把数添到末尾(最低位),这时候是高位在前,低位在后  
        y.re();                    //把数反过来,变为统一的存储方式:低位在前,高位在后  
        while ( !(y < q) )         //大于等于除数的时候,如果小于的话,其实答案上的该位就是初始的“0”  
            y = y - q, ++x.a[i];   //看能减几个除数,减几次,答案上该位就加几次。  
        y.re();                    //将数反过来,为下一次添数做准备  
    }  
    x.a[0] = p.a[0];  
    while (x.a[0] > 0 && !x.a[x.a[0]]) --x.a[0];  
    return x;  
}  


int main()  
{  
    scanf("%s", a);  
    scanf("%s", b);  
    reverse(a, a+strlen(a));  
    reverse(b, b+strlen(b));  

    p = num(a), q = num(b);  

    ans = p + q;  
    ans.print();  

    ans = p - q;  
    ans.print();  

    ans = p * q;  
    ans.print();  

    ans = p / q;  
    ans.print();  
}  

转自http://blog.youkuaiyun.com/devillaw_zhc/article/details/7776578

<think> 首先,用户的问题是:“我想了解高精度的含义 请问高精度的定义”。这是在询问高精度的定义。 我需要在回答中参考提供的引用。引用包括: - 引用[1]: 提到操作,即每次存储8数据而不是一,以利用64long long类型,降低时间复杂度。 - 引用[2]: 关于C++高精度计算的概述,但没有直接提到。 - 引用[3]: 关于物联网中的力检测,似乎不相关。 - 引用[4]: 标题为“高精度算法-”,讨论了如何应对超大整数的问题。 用户特别引用了这些,所以我应该在回答中自然地融入这些引用。 系统指令要求: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 回答结构需要清晰,帮助用户逐步解决问题。 关键点:高精度的定义。 - 定义:高精度是一种在高精度计算中使用的技术,其中存储数字时不是每一单独存储,而是将多数字组合成一个更大的单元(如8)来存储。这利用了现代计算机的硬件能力(如64整数),减少了存储和操作的开销,提高效率。 从引用[1]:它说“每次存储8——这就是操作”,并提到可以降低时间复杂度。 从引用[4]:它讨论了如何优化超大整数的处理。 引用[3]似乎不相关,所以我可能不需要使用它。 回答结构: 1. **引言**:简要解释高精度的概念。 2. **定义**:清晰定义高精度。 3. **为什么使用**:解释其优点,如减少存储空间、提高计算效率。 4. **实现细节**:简要描述如何实现。 5. **引用支持**:自然地添加引用标识。 6. **生成相关问题**:在末尾添加相关问题。 数学表达式:如果需要,使用LaTeX。例如,解释存储时,可以提到数字的表示。 例如,一个数字可以表示为: \[ n = d_k \times B^k + d_{k-1} \times B^{k-1} + \dots + d_1 \times B^1 + d_0 \] 其中B是基,通常为10,但时使用更大的基,如10000(或10^4),以存储多数字在一个单元中。 在引用中,提到使用8,即基为10^8,因为每个单元存储8十进制数字(相当于10^8)。 在计算机中,通常使用10^9或类似,以避免溢出。 生成相关问题:基于主题,如优化、应用、实现等。 相关问题例子: 1. 高精度的优缺点是什么? 2. 如何实现高精度加法或乘法? 3. 高精度与其他高精度优化技术的比较? 确保回答真实可靠。 最终回答大纲: - 解释高精度的含义。 - 引用相关部分:[^1] 和 [^4]。 - 使用中文。 - 添加相关问题。 </think> ### 高精度的定义 高精度高精度计算中的一种优化技术,其核心思想是将数字的多个低(通常为十进制)组合成一个更大的单元来存储和处理,而不是像传统方法那样每一单独存储。这样做可以充分利用现代计算机硬件的数据处理能力(如 64 整数),减少存储开销和计算步骤,从而显著提高算法的效率和性能。具体来说: - **核心概念**:在标准高精度计算中,一个数字(如一个大整数)通常以十进制形式存储在数组中,每个元素表示数字的一(例如,数字 12345 表示为数组 [1, 2, 3, 4, 5])。高精度则采用更大的基(base),比如将每 8 十进制数字组合成一个单独的“单元”(unit),存储在更大的数据类型中(如 `long long` 类型)。例如: - 如果基 $B = 10^8$(即 100,000,000),那么一个单元可以表示 0 到 99,999,999 之间的值。 - 数字的数学表示为: \[ n = d_k \times B^k + d_{k-1} \times B^{k-1} + \dots + d_1 \times B^1 + d_0 \] 其中 $d_i$ 是每个单元的值,$B$ 是基(通常为 $10^8$),$k$ 是单元索引。 - **为什么使用**:传统的逐存储方式在操作超大整数(如百万或更大)时,效率低下: - **存储浪费**:每次只存储一十进制数字(占用 1 个字节或更少),但现代计算机支持 64 整数(可存储高达 $2^{64} \approx 1.8 \times 10^{19}$ 的值),利用了这一优势,减少了数组大小和内存占用[^1]。 - **性能提升**:运算(如加法和乘法)的复杂度从 $O(n^2)$ 降低到 $O(n)$ 或更低,因为每次操作单更大,减少了循环次数。例如,乘法运算中,可将进处理次数降到最低,避免溢出问题[^1][^4]。 - **典型实现**:在编程中,高精度通常使用整数数组实现,每个元素存储多数字。例如,在 C++ 中,可以使用 `long long` 数组,每个元素存储 8 十进制数字(基 $10^8$),以确保乘法时不会溢出(因为 $10^8 \times 10^8 = 10^{16} < 2^{64}$)[^1]。算法在模板库中常见,适用于大整数运算(如阶乘或斐波那契数列计算),尤其在处理超大规模数据时(如 $10000^{10000}$ 整数),避免数组大小限制[^4]。 总之,高精度是一种高效的高精度算法策略,通过“缩”数字来优化时间和空间复杂度,特别适合处理科学计算、密码学或大数据场景中的超大整数问题[^1][^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值