大数(高精度数)模板(分享)

 更新时间:2013年05月24日 16:51:05   作者:  
本篇文章对大数(高精度数)模板进行了详细的分析介绍,需要的朋友参考下
复制代码 代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h> 
#include <ctype.h>
#include <map>
#include <string>
#include <set>
#include <bitset>
#include <utility>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <iostream>
#include <fstream>
#include <list>
using  namespace  std;     

const  int MAXL = 500;     
struct  BigNum     
{     
    int  num[MAXL];     
    int  len;     
};     

//高精度比较 a > b return 1, a == b return 0; a < b return -1;     
int  Comp(BigNum &a, BigNum &b)     
{     
    int  i;     
    if(a.len != b.len) return (a.len > b.len) ? 1 : -1;     
    for(i = a.len-1; i >= 0; i--)     
        if(a.num[i] != b.num[i]) return  (a.num[i] > b.num[i]) ? 1 : -1;     
    return  0;     
}     

//高精度加法     
BigNum  Add(BigNum &a, BigNum &b)     
{     
    BigNum c;     
    int  i, len;     
    len = (a.len > b.len) ? a.len : b.len;     
    memset(c.num, 0, sizeof(c.num));     
    for(i = 0; i < len; i++)     
    {     
        c.num[i] += (a.num[i]+b.num[i]);     
        if(c.num[i] >= 10)     
        {     
            c.num[i+1]++;     
            c.num[i] -= 10;     
        }     
    }     
    if(c.num[len])
  len++;     
    c.len = len;     
    return  c;     
}     
//高精度减法,保证a >= b     
BigNum Sub(BigNum &a, BigNum &b)     
{     
    BigNum  c;     
    int  i, len;     
    len = (a.len > b.len) ? a.len : b.len;     
    memset(c.num, 0, sizeof(c.num));     
    for(i = 0; i < len; i++)     
    {     
        c.num[i] += (a.num[i]-b.num[i]);     
        if(c.num[i] < 0)     
        {     
            c.num[i] += 10;     
            c.num[i+1]--;     
        }     
    }     
    while(c.num[len] == 0 && len > 1)
  len--;     
    c.len = len;     
    return  c;     
}     
//高精度乘以低精度,当b很大时可能会发生溢出int范围,具体情况具体分析     
//如果b很大可以考虑把b看成高精度     
BigNum Mul1(BigNum &a, int  &b)     
{     
    BigNum c;     
    int  i, len;     
    len = a.len;     
    memset(c.num, 0, sizeof(c.num));     
    //乘以0,直接返回0     
    if(b == 0)      
    {     
        c.len = 1;     
        return  c;     
    }     
    for(i = 0; i < len; i++)     
    {     
        c.num[i] += (a.num[i]*b);     
        if(c.num[i] >= 10)     
        {     
            c.num[i+1] = c.num[i]/10;     
            c.num[i] %= 10;     
        }     
    }     
    while(c.num[len] > 0)     
    {     
        c.num[len+1] = c.num[len]/10;     
        c.num[len++] %= 10;     
    }     
    c.len = len;      
    return  c;     
}     

//高精度乘以高精度,注意要及时进位,否则肯能会引起溢出,但这样会增加算法的复杂度,     
//如果确定不会发生溢出, 可以将里面的while改成if     
BigNum  Mul2(BigNum &a, BigNum &b)     
{     
    int i, j, len = 0;     
    BigNum  c;     
    memset(c.num, 0, sizeof(c.num));     
    for(i = 0; i < a.len; i++)
 {
        for(j = 0; j < b.len; j++)     
        {     
            c.num[i+j] += (a.num[i]*b.num[j]);     
            if(c.num[i+j] >= 10)     
            {     
                c.num[i+j+1] += c.num[i+j]/10;     
                c.num[i+j] %= 10;     
            }     
        }
 }
    len = a.len+b.len-1;     
    while(c.num[len-1] == 0 && len > 1)
  len--;     
    if(c.num[len])
  len++;     
    c.len = len;     
    return  c;     
}     

//高精度除以低精度,除的结果为c, 余数为f     
void Div1(BigNum &a, int &b, BigNum &c, int &f)     
{     
    int  i, len = a.len;     
    memset(c.num, 0, sizeof(c.num));     
    f = 0;     
    for(i = a.len-1; i >= 0; i--)     
    {     
        f = f*10+a.num[i];     
        c.num[i] = f/b;     
        f %= b;     
    }     
    while(len > 1 && c.num[len-1] == 0)
  len--;     
    c.len = len;     
}     
//高精度*10     
void  Mul10(BigNum &a)     
{     
    int  i, len = a.len;     
    for(i = len; i >= 1; i--)     
        a.num[i] = a.num[i-1];     
    a.num[i] = 0;     
    len++;     
    //if a == 0     
    while(len > 1 && a.num[len-1] == 0)
  len--;     
}     

//高精度除以高精度,除的结果为c,余数为f     
void Div2(BigNum &a, BigNum &b, BigNum &c, BigNum &f)     
{     
    int  i, len = a.len;     
    memset(c.num, 0, sizeof(c.num));     
    memset(f.num, 0, sizeof(f.num));     
    f.len = 1;     
    for(i = len-1;i >= 0;i--)     
    {     
        Mul10(f);     
        //余数每次乘10     
        f.num[0] = a.num[i];     
        //然后余数加上下一位     
        ///利用减法替换除法     
        while(Comp(f, b) >= 0)     
        {
            f = Sub(f, b);     
            c.num[i]++;     
        }     
    }     
    while(len > 1 && c.num[len-1] == 0)
  len--;     
    c.len = len;     
}  
void  print(BigNum &a)   //输出大数  
{     
    int  i;     
    for(i = a.len-1; i >= 0; i--)     
        printf("%d", a.num[i]);     
    puts("");     
}     
//将字符串转为大数存在BigNum结构体里面     
BigNum ToNum(char *s)     
{     
    int i, j;     
    BigNum  a;     
    a.len = strlen(s);     
    for(i = 0, j = a.len-1; s[i] != '\0'; i++, j--)     
        a.num[i] = s[j]-'0';     
    return  a;     
}     

void Init(BigNum &a, char *s, int &tag)   //将字符串转化为大数
{  
    int  i = 0, j = strlen(s);
    if(s[0] == '-')
 {
  j--;
  i++;
  tag *= -1;
 }
    a.len = j;
    for(; s[i] != '\0'; i++, j--)
        a.num[j-1] = s[i]-'0';
}  

int main(void)     
{     
    BigNum a, b;  
    char  s1[100], s2[100];  
    while(scanf("%s %s", s1, s2) != EOF)  
    {  
        int tag = 1;  
        Init(a, s1, tag);    //将字符串转化为大数
        Init(b, s2, tag);  
        a = Mul2(a, b);  
        if(a.len == 1 && a.num[0] == 0)  
        {  
            puts("0");  
        }  
        else   
        {  
            if(tag < 0) putchar('-');  
            print(a);  
        }  
    }  
    return 0;  
}

相关文章

  • 深入解析C++中的动态类型转换与静态类型转换运算符

    深入解析C++中的动态类型转换与静态类型转换运算符

    这篇文章主要介绍了C++中的动态类型转换与静态类型转换运算符,即dynamic_cast与static_cast的用法,需要的朋友可以参考下
    2016-01-01
  • C++基础学习之利用两个栈实现一个队列

    C++基础学习之利用两个栈实现一个队列

    这篇文章主要给大家介绍了关于C++基础学习之利用两个栈实现一个队列的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C++具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-05-05
  • C++链表节点的添加和删除介绍

    C++链表节点的添加和删除介绍

    大家好,本篇文章主要讲的是C++链表节点的添加和删除介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • 利用C++实现简易的.ini配置文件解析器

    利用C++实现简易的.ini配置文件解析器

    这篇文章主要为大家详细介绍了如何基于C++编写一个简易的.ini配置文件解析器,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以了解一下
    2023-03-03
  • C语言三子棋的实现思路到过程详解

    C语言三子棋的实现思路到过程详解

    所谓三子棋,就是三行三列的棋盘,玩家可以和电脑下棋,率先连成三个的获胜。这篇文章主要为大家详细介绍了如何通过C语言实现三子棋小游戏,感兴趣的小伙伴可以尝试一下
    2023-02-02
  • C语言简明分析指针与引用的具体用法

    C语言简明分析指针与引用的具体用法

    指针是一个实体,引用是一个别名;在汇编上,引用的底层是以指针的方式实现的,定义一个引用变量,相当于定义了一个指针,然后把引用内存的地址写到这个指针里面,当通过引用变量修改它所引用的内存时,它先访问了指针里面的地址,然后在这个地址的内存里面对值进行修改
    2022-05-05
  • C语言每日练习之冒泡排序

    C语言每日练习之冒泡排序

    这篇文章主要介绍了C语言冒泡排序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-11-11
  • C++实现简单单向链表

    C++实现简单单向链表

    这篇文章主要为大家详细介绍了C++实现简单单向链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • C语言关于时间复杂度详解

    C语言关于时间复杂度详解

    大家好,本篇文章主要讲的是C语言关于时间复杂度详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • C语言基础 原码、反码、补码和移码详解

    C语言基础 原码、反码、补码和移码详解

    这篇文章主要介绍了C语言基础 原码、反码、补码和移码详解的相关资料,需要的朋友可以参考下
    2017-01-01

最新评论