C++高精度模板
原文地址: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++高精度模板的更多相关文章
- [Template]高精度模板
重新写一下高精度模板(不要问我为什么) 自认为代码风格比较漂亮(雾 如果有更好的写法欢迎赐教 封装结构体big B是压位用的进制,W是每位长度 size表示长度,d[]就是保存的数字,倒着保存,从1开 ...
- [note]高精度模板
高精度模板 先定义一个struct struct gj{ int l,s[N]; bool fh; void Print(){ if(fh)putchar('-'); for(int i=l;i> ...
- 高精度模板 支持各种运算 c++
绪言 自从有了高精度模板,妈妈再也不用怕我不会打高精度了! 代码 代码长度与日俱增啊~~~ #include<iostream> #include<cstring> #incl ...
- 高精度模板 Luogu P1932 A+B & A-B & A*B & A/B Problem
P1932 A+B & A-B & A*B & A/B Problem 题目背景 这个题目很新颖吧!!! 题目描述 求A.B的和差积商余! 输入输出格式 输入格式: 两个数两行 ...
- Java 大数、高精度模板
介绍: java中用于操作大数的类主要有两个,一个是BigInteger,代表大整数类用于对大整数进行操作,另一个是BigDecimal,代表高精度类,用于对比较大或精度比较高的浮点型数据进行操作.因 ...
- JAVA高精度模板
刚开始还坚持用C++写高精来着,后来发现JAVA写高精方便太多了,所以也来学习一下JAVA高精度的模板. 参考:https://www.cnblogs.com/imzscilovecode/p/883 ...
- 高精度模板 洛谷Luogu P1932 A+B & A-B & A*B & A/B Problem
P1932 A+B & A-B & A*B & A/B Problem 题目背景 这个题目很新颖吧!!! 题目描述 求A.B的和差积商余! 输入输出格式 输入格式: 两个数两行 ...
- [SinGuLaRiTy] 复习模板-高精度模板
[SinGuLaRiTy-1042] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 结构体封装 //高精度运算 注意%I64d与%lld # ...
- XDOJ 1046 - 高精度模板综合测试 - [高精度模板]
题目链接:http://acm.xidian.edu.cn/problem.php?id=1046 题目描述 请输出两个数的和,差,积,商,取余.注意不要有前导零. 输入 多组数据,每组数据是两个整数 ...
随机推荐
- postman断言作用及怎么使用
这段时间一直在学习postman,在请求中使用断言,很多人不是很了解postman断言,其实呢,postman断言是JavaScript语言编写的,在postman客户端指定区域编写即可. 1.设置环 ...
- vueJS 获取后台数据 绑定data
//vue 环境安装http://blog.csdn.net/u013182762/article/details/53021374 一开始使用安装环境配置一些东西 ,后来发现太麻烦了 . 直接CD ...
- yum仓库,RPM打包
rpm命令: -qa 查看软件包是否被安装 -ivh 安装rpm包 -e 卸载包 -qpl 查看rpm包中有什么东西 -qi 查看软件的详细安装信息:安装路径 安装fpm #FPM是Ruby模块yu ...
- ORACLE JOB创建
Connected Connected as focususer SQL> SQL> --JOB 需要在命令行执行: SQL> --抽数job SQL> CREATE OR R ...
- Android™ 1.5 android.R.drawable Icon Resources
图标一览表: http://www.darshancomputing.com/android/1.5-drawables.html 官 方 API: http://developer.androi ...
- SIM9001GSM模块教程
博主最近在做一个项目,用到了GSM模块,博主不是什么单片机大神,只是感觉某宝附带的资料太水,所以上传一些自己写的程序和经验,供需要的人参考 1,拨打电话 /********************** ...
- 关于binary log一点总结[转]
阅读目录(Content) 1 what's binary log 2 Binary Logging Options and Variables 2.1 基础参数 3 Binary Logging F ...
- EasyUI之Hello world(EasyUI的入门学习)
1:创建一个动态web工程: 去官网http://www.jeasyui.net/download/下载官网文档 我去官网下载的最新版本,个人根据自己的需求下载即可.2:在webConte ...
- 使用Dubbox构架分布式服务
第一部分:Dubbo的背景分析及工作原理 1. Dubbo是什么?Dubbo是一个来自阿里巴巴的开源分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案. 简单的说 ...
- Instrument详解
Instruments用户指南介绍Instruments是应用程序用来动态跟踪和分析Mac OS X和iOS代码的实用工具.这是一个灵活而强大的工具,它让你可以跟踪一个或多个进程,并检查收集的数据.这 ...