原文地址:http://blog.csdn.net/wall_f/article/details/8373395

原文只附代码,没有解析,本文增加了一些对代码的解释

请注意:本模板不涉及实数运算与负数运算,使用减法a-b时请保证, a >= b;所有用本模板来转化的数需保证a >0 && a无小数部分。


引:
题目中涉及到高精度运算在信息学竞赛中并不少见,很多题目得不到全分就是因为选手不会写高精度模板。尽管AC过高精度(+,*,-,//除法麻烦一点)模板题,但是对于将高精度写入结构体使得可以正常运算的bign模板,很多选手只是有所听闻而不会写。其实写起来并不难,只是将原来那些模板题写入运算符重载即可

建议背下来,OI比赛中指不定就撞上了,现推也可以,但是比较慢,至少保证熟练

运算涉及
Bool型:== 、> 、< 、 >= 、 <= 、 !=
赋值语句:= 、 +=、 -=、 *=、 /=、 %=
运算符:+ 、- 、 * 、 /、 %

其中 (?)= 赋值运算符的重载最为好写,直接调用已经重载完成的(?)运算符,再返回当前this。(? includes + - / %)

其次便是bool型。> < 分别用字符串的比较的比较方式重载,其余的只需要将它们组合一下。例如 == : !(>) && !(<)。

难点在于除法运算符的重载

我们定义一个结构体包含一个整型int(长度)与数组s(存每一位)组成,其中数组是反着存的。


#include <bits/stdc++.h> 

using namespace std;

const int MAXN = 5005;  

struct bign
{
int len, s[MAXN];
bign () //初始化
{
memset(s, 0, sizeof(s));
len = 1;
}
bign (int num) { *this = num; }
bign (const char *num) { *this = num; } //让this指针指向当前字符串
bign operator = (const int num)
{
char s[MAXN];
sprintf(s, "%d", num); //sprintf函数将整型映到字符串中
*this = s;
return *this; //再将字符串转到下面字符串转化的函数中
}
bign operator = (const char *num)
{
for(int i = 0; num[i] == '0'; num++) ; //去前导0
len = strlen(num);
for(int i = 0; i < len; i++) s[i] = num[len-i-1] - '0'; //反着存
return *this;
}
bign operator + (const bign &b) const //对应位相加,最为简单
{
bign c;
c.len = 0;
for(int i = 0, g = 0; g || i < max(len, b.len); i++)
{
int x = g;
if(i < len) x += s[i];
if(i < b.len) x += b.s[i];
c.s[c.len++] = x % 10; //关于加法进位
g = x / 10;
}
return c;
}
bign operator += (const bign &b) //如上文所说,此类运算符皆如此重载
{
*this = *this + b;
return *this;
}
void clean() //由于接下来的运算不能确定结果的长度,先大而估之然后再查
{
while(len > 1 && !s[len-1]) len--; //首位部分‘0’故删除该部分长度
}
bign operator * (const bign &b) //乘法重载在于列竖式,再将竖式中的数转为抽象,即可看出运算法则。
{
bign c;
c.len = len + b.len;
for(int i = 0; i < len; i++)
{
for(int j = 0; j < b.len; j++)
{
c.s[i+j] += s[i] * b.s[j];//不妨列个竖式看一看
}
}
for(int i = 0; i < c.len; i++) //关于进位,与加法意同
{
c.s[i+1] += c.s[i]/10;
c.s[i] %= 10;
}
c.clean(); //我们估的位数是a+b的长度和,但可能比它小(1*1 = 1)
return c;
}
bign operator *= (const bign &b)
{
*this = *this * b;
return *this;
}
bign operator - (const bign &b) //对应位相减,加法的进位改为借1
{ //不考虑负数
bign c;
c.len = 0;
for(int i = 0, g = 0; i < len; i++)
{
int x = s[i] - g;
if(i < b.len) x -= b.s[i]; //可能长度不等
if(x >= 0) g = 0; //是否向上移位借1
else
{
g = 1;
x += 10;
}
c.s[c.len++] = x;
}
c.clean();
return c;
}
bign operator -= (const bign &b)
{
*this = *this - b;
return *this;
}
bign operator / (const bign &b) //运用除是减的本质,不停地减,直到小于被减数
{
bign c, f = 0; //可能会在使用减法时出现高精度运算
for(int i = len-1; i >= 0; i--) //正常顺序,从最高位开始
{
f = f*10; //上面位的剩余到下一位*10
f.s[0] = s[i]; //加上当前位
while(f >= b)
{
f -= b;
c.s[i]++;
}
}
c.len = len; //估最长位
c.clean();
return c;
}
bign operator /= (const bign &b)
{
*this = *this / b;
return *this;
}
bign operator % (const bign &b) //取模就是除完剩下的
{
bign r = *this / b;
r = *this - r*b;
r.clean();
return r;
}
bign operator %= (const bign &b)
{
*this = *this % b;
return *this;
}
bool operator < (const bign &b) //字符串比较原理
{
if(len != b.len) return len < b.len;
for(int i = len-1; i != -1; i--)
{
if(s[i] != b.s[i]) return s[i] < b.s[i];
}
return false;
}
bool operator > (const bign &b) //同理
{
if(len != b.len) return len > b.len;
for(int i = len-1; i != -1; i--)
{
if(s[i] != b.s[i]) return s[i] > b.s[i];
}
return false;
}
bool operator == (const bign &b)
{
return !(*this > b) && !(*this < b);
}
bool operator != (const bign &b)
{
return !(*this == b);
}
bool operator <= (const bign &b)
{
return *this < b || *this == b;
}
bool operator >= (const bign &b)
{
return *this > b || *this == b;
}
string str() const //将结果转化为字符串(用于输出)
{
string res = "";
for(int i = 0; i < len; i++) res = char(s[i]+'0')+res;
return res;
}
}; istream& operator >> (istream &in, bign &x) //重载输入流
{
string s;
in >> s;
x = s.c_str(); //string转化为char[]
return in;
} ostream& operator << (ostream &out, const bign &x) //重载输出流
{
out << x.str();
return out;
} int main()
{
bign a;//除了声明外其他如整型般使用
//……
return 0;
}

感谢原作者。

不妨运用一下:
luogu P1601 A+B Problem(高精) https://www.luogu.org/problem/show?pid=1601
luogu P2142 高精度减法 https://www.luogu.org/problem/show?pid=2142
luogu P1303 A*B Problem https://www.luogu.org/problem/show?pid=1303
luogu P1480 A/B Problem https://www.luogu.org/problem/show?pid=1480

不妨思考一下其他高精度运算:
luogu:P2293 [HNOI2004]高精度开根 https://www.luogu.org/problem/show?pid=2293

高精度模板至此结束。
箜瑟_qi 2017.04.08 9:53

C++高精度模板的更多相关文章

  1. [Template]高精度模板

    重新写一下高精度模板(不要问我为什么) 自认为代码风格比较漂亮(雾 如果有更好的写法欢迎赐教 封装结构体big B是压位用的进制,W是每位长度 size表示长度,d[]就是保存的数字,倒着保存,从1开 ...

  2. [note]高精度模板

    高精度模板 先定义一个struct struct gj{ int l,s[N]; bool fh; void Print(){ if(fh)putchar('-'); for(int i=l;i> ...

  3. 高精度模板 支持各种运算 c++

    绪言 自从有了高精度模板,妈妈再也不用怕我不会打高精度了! 代码 代码长度与日俱增啊~~~ #include<iostream> #include<cstring> #incl ...

  4. 高精度模板 Luogu P1932 A+B & A-B & A*B & A/B Problem

    P1932 A+B & A-B & A*B & A/B Problem 题目背景 这个题目很新颖吧!!! 题目描述 求A.B的和差积商余! 输入输出格式 输入格式: 两个数两行 ...

  5. Java 大数、高精度模板

    介绍: java中用于操作大数的类主要有两个,一个是BigInteger,代表大整数类用于对大整数进行操作,另一个是BigDecimal,代表高精度类,用于对比较大或精度比较高的浮点型数据进行操作.因 ...

  6. JAVA高精度模板

    刚开始还坚持用C++写高精来着,后来发现JAVA写高精方便太多了,所以也来学习一下JAVA高精度的模板. 参考:https://www.cnblogs.com/imzscilovecode/p/883 ...

  7. 高精度模板 洛谷Luogu P1932 A+B & A-B & A*B & A/B Problem

    P1932 A+B & A-B & A*B & A/B Problem 题目背景 这个题目很新颖吧!!! 题目描述 求A.B的和差积商余! 输入输出格式 输入格式: 两个数两行 ...

  8. [SinGuLaRiTy] 复习模板-高精度模板

    [SinGuLaRiTy-1042] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 结构体封装 //高精度运算 注意%I64d与%lld # ...

  9. XDOJ 1046 - 高精度模板综合测试 - [高精度模板]

    题目链接:http://acm.xidian.edu.cn/problem.php?id=1046 题目描述 请输出两个数的和,差,积,商,取余.注意不要有前导零. 输入 多组数据,每组数据是两个整数 ...

随机推荐

  1. webpack 打包js和css

    首先进行全局安装webpack npm install -g webpackcmd跳转到项目的文件夹,安装webpack npm install --save-dev webpack接着需要packj ...

  2. linux ip 转发设置 ip_forward

    工作原理: 内网主机向公网发送数据包时,由于目的主机跟源主机不在同一网段,所以数据包暂时发往内网默认网关处理,而本网段的主机对此数据包不做任何回应.由于源主机ip是私有的,禁止在公网使用,所以必须将数 ...

  3. CSS.01 -- 选择器及相关的属性文本、文字、字体、颜色、

    与html相比,Css支持更丰富的文档外观,Css可以为任何元素的文本和背景设置颜色:允许在任何元素外围设置边框:允许改变文本的大小,装饰(如下划线),间隔,甚至可以确定是否显示文本. 什么是CSS? ...

  4. 模块“XXX.dll”加载失败

    具体问题:模块“XXX.dll”加载失败 请确保该二进制存储在指定的路径中,或者调试它以检查该二进制或相关的.DLL文件是否有问题  找不到指定的模块. 1.在安装C++软件的时候,有时候安装失败提示 ...

  5. unity插件开发——MenuItem

    有unity中的菜单栏是我们经常使用到的地方,如下图: MenuItem的作用就是增加一个自己的菜单 使用方法: 在工程中Assets目录下任意一个Editor目录(以后简称Editor目录,如果不存 ...

  6. 【JavaWeb】Session(转)

    Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自 ...

  7. Truncated incorrect DOUBLE value错误

    mysql报错:Truncated incorrect DOUBLE value sql的update语法错误eg: update Person set name = 'auhnayuiL' and ...

  8. TCP/IP笔记(四)IP协议

    前言 IP相当于OSI参考模型的第3层--网络层:主要作用是"实现终端节点之间的通信"又称"点对点通信". IP作为整个TCP/IP中至关重要的协议,主要负责将 ...

  9. linux sort命令详解(转)

    sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式: sort [-bcfMnrtk][源文件][-o 输出文件] 补充说明:sort可针对文本文件的内容,以行为单位来排序. 参 数 ...

  10. metools,不花一分钱就能拥有自己的工具站点?

    需要[加密/解密][编码/解码][生成二维码]的时候不用再进百度点广告~ 也不需要去收藏夹找网址~ 我的目的大概就是如此. 项目地址:https://github.com/yimogit/metool ...