原文地址: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. SpringMVC搭建+实例

    想做一点自己喜欢的东西,研究了一下springMVC,所以就自己搭建一个小demo,可供大家吐槽. 先建一个WEB工程,这个相信大家都会,这里不在多说. 去网上下载spring jar包,然后在WEB ...

  2. [笔记]LR和SVM的相同和不同

    之前一篇博客中介绍了Logistics Regression的理论原理:http://www.cnblogs.com/bentuwuying/p/6616680.html. 在大大小小的面试过程中,经 ...

  3. 解决VIM编辑器中文乱码

    追加如下内容到/etc/vimr (或者不同的用户家目录下的.vimrc文件中) set encoding=utf8filetype plugin indent onsyntax on" s ...

  4. require include php5中最新区别,百度上好多错的。

    二者报错机制不同,include是warning 继续执行程序,require会报致命错误,中断程序运行. 前者有返回值,后者则没有. 注意了,php5里有一个区别没了,之前说的是require是无条 ...

  5. python爬虫实战(一)--------中国作物种质信息网

    相关代码已经修改调试成功----2017-4-1 目标网址:http://www.cgris.net/query/croplist.php 实现:爬取相关信息如图所示,爬取的数据存入mysql数据库. ...

  6. Java面试步步走

    一.Java 基础 1.Java 集合原理 2.Java 多线程.同步集合.并发集合.阻塞队列.线程池.各种锁等 3.JVM 垃圾回收机制.JVM 引用类型.JVM 内存模型 二.应用技术基础 1)数 ...

  7. 转接口IC GM7122:BT656转CVBS芯片 视频编码电路

    1 概述    视频编码电路主要实现接收8位CCIR656格式的YUV数据,(例如MPEG解码数据),并编码成CVBS信号,经过D/A转换后输出.基本的编码功能包括副载波产生,色差信号调制,同步信号内 ...

  8. 【微信开发】PHP中奖概率经典算法实例

    $arr=array("50","30","20"); //这里简单列出三个数 $pro = array_sum($arr); // 概率数 ...

  9. 20155304 实验一《Java开发环境的熟悉》实验报告

    20155304 实验一实验报告 实验一 Java开发环境的熟悉 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用IDEA编译.编译.运行.调试Java程序. 实验步骤 (一)命令行下 ...

  10. mui上拉加载

    最近在做移动端的项目,用到了mui的上拉加载,整理如下: 1.需要引入的css.js <link rel="stylesheet" href="common/mui ...