原文地址: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. WINFROM 无边框窗体的移动和改变大小

    因为去掉了边框  移动和调整大小都用不了了,可以调用WIN32的API来实现 1.定义必须常量 ; ; ; ; ; ; const int Guying_HTBOTTOMLEFT = 0x10; ; ...

  2. Android getAttributeIntValue()详解-霞辉

    经常使用getAttributeIntValue()方法,但是大多使用的形式是attrs.getAttributeFloatValue(null, "xxx", 0);只是在中间传 ...

  3. 5种方法推导Normal Equation

    引言: Normal Equation 是最基础的最小二乘方法.在Andrew Ng的课程中给出了矩阵推到形式,本文将重点提供几种推导方式以便于全方位帮助Machine Learning用户学习. N ...

  4. UICollectionView 适配 iPhone 7 Plus

    UICollectionView 适配 iPhone 7 Plus 需求:在屏幕上水平放置 5 张正方形图片,每张图片的宽度相等,无缝隙排列铺满一个屏幕宽度. 看似很简单的需求.用 UICollect ...

  5. 修复关于apache-xampp的问题:Port 443 in use by “vmware-hostd.exe”!

    内容提要:复关于apache-xampp的问题:Port 443 in use by “vmware-hostd.exe”!在电脑里装了VMware后,再要装xampp,十有八九就会出现这个问题: 复 ...

  6. Java 垃圾回收(GC) 泛读

    Java 垃圾回收(GC) 泛读 文章地址:https://segmentfault.com/a/1190000008922319 0. 序言 带着问题去看待 垃圾回收(GC) 会比较好,一般来说主要 ...

  7. 手机自动化测试:appium问题解决

    手机自动化测试:appium问题解决   Appium遇到问题: 问题一:问题org.openqa.selenium.remote.UnreachableBrowserException: Could ...

  8. Linux文件管理上

    Linux文件管理   作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 对于计算机来说,所谓的数据就是0和1的序列.这样的一个序列 ...

  9. DUBBO高级配置:多注册中心配置

    有时候我们需要的服务不在同一个 zookeeper 注册中心上,此时我们需要在 DUBBO 配置文件中配置多个注册中心. 下面我们在之前创建项目的基础上在 provider 模块中增加一个 IBook ...

  10. 2017携程Web前端实习生招聘笔试题总结

    考察encodeURI encodeURI(), decodeURI()它们都是Global对象的方法. encodeURI()通过将某些字符的每个实例替换代表字符的UTF-8编码的一个或多个转义字符 ...