绪言

自从有了高精度模板,妈妈再也不用怕我不会打高精度了!

代码

代码长度与日俱增啊~~~

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std; bool insigma(char ch){
return ch=='-'||(''<=ch&&ch<='');
} const int maxn = ;
struct number{
int num[maxn];
int len;
bool fu; number(){//初始化
len=fu=;
memset(num,,sizeof(num));
} int updata_len(){//更新长度
for(int i=maxn-;i>=;i--) if(num[i]) return len=i+;
return len=;
} // /*
number operator= (int x){//隐式转换
fu=(x<);
num[]=abs(x);
if(x>) carry_bit();
if(x<-) back_space();
return *this;
}
// */
/*
number (int x){//有bug的构造函数 暂时用重载=替代
fu=(x<0);
num[0]=abs(x);
if(x>9) carry_bit();
if(x<-9) back_space();
}
*/ void input(){
// /*
string a;
cin>>a;
if(a[]=='-'){
fu=;
len=a.size()-;
for(unsigned int i=;i<a.size()-;i++) num[i]=a[a.size()-i-]-'';
}
else{
len=a.size();
for(unsigned int i=;i<a.size();i++) num[i]=a[a.size()-i-]-'';
} // */
/*
len=0;
char ch;
while(!insigma(ch=getchar()));
if(ch=='-')
fu=true;
else
num[len++]=ch-'0';
while(isdigit(ch=getchar())){
num[len++]=ch-'0';
}
int t;
for(int i=0;i<len;i++)
{
t=num[i];
num[i]=num[len-i-1];
num[len-i-1]=t;
}
*/
} void output(){
if(fu) cout<<"-";
bool flag=;
for(int i=len;i>;i--){
if(num[i]) flag=;
if(num[i]>) carry_bit();
if(flag) putchar(num[i]+'');//putchar加速
}
putchar(num[]+'');
} friend istream & operator>> (istream &in, number &obj);
friend ostream & operator<< (ostream &out, number &obj); int compare(number x){//2= 1> 0<
if(fu^x.fu){
if(fu) return ;
else return ;
}
for(int i=max(len,x.len);i>=;i--)
{
if(num[i]>x.num[i]) return !fu;//大于 (1)
if(num[i]<x.num[i]) return fu;//小于 (0)
}
return ;//相等
} //利用compare()重载比较运算符 bool operator> (number x){
return (compare(x)==);
} bool operator< (number x){
return (compare(x)==);
} bool operator>= (number x){
return !(*this<x);
} bool operator<= (number x){
return !(*this>x);
} bool operator== (number x){
return compare(x)==;
} bool operator!= (number x){
return compare(x)!=;
} number operator++ (){
num[]++;
if(num[]>) carry_bit();
return *this;
} number operator++ (int){
number save=*this;
++*this;
return save;
} number operator-- (){
num[]--;
if(num[]<) back_space();
return *this;
} number operator-- (int){
number save=*this;
num[]--;
if(num[]<) back_space();
return save;
} bool judge_zero(){
for(int i=maxn-;i>=;i--)
if(num[i]) return ;
return ;
} bool judge_non_zero(){
return !judge_zero();
} bool convert_bool(){
return !judge_zero();
} bool even(){
if(num[]%) return ;
return ;
} bool odd(){
if(num[]%) return ;
return ;
} void carry_bit(){
for(int i=;i<maxn;i++){
num[i+]+=num[i]/;
num[i]%=;
}
updata_len();
} void back_space(){
for(int i=;i<maxn;i++){
while(num[i]<) num[i]+=,num[i+]--;
}
} number operator+ (int x){
number newness=*this;
newness.num[]+=x;
if(newness.num[]>) newness.carry_bit();
return newness;
} number operator+ (number x){
number res=x;
for(int i=;i<maxn;i++)
{
res.num[i]+=num[i];
}
res.carry_bit();
return res;
} number operator+= (int x){
*this=(*this+x);
return *this;
} number operator+= (number x){
*this=*this+x;
return *this;
} number operator- (number x){
number i,j;
if(compare(x)) {i=*this,j=x;}
else {i=x,j=*this;}
for(int t=;t<maxn;t++)
{
i.num[t]-=j.num[t];
}
i.back_space();
return i;
} number operator-= (number x){
*this=*this-x;
return *this;
} number operator* (number x){
number sum;
sum.fu=fu^x.fu;
for(int i=;i<updata_len();i++)
for(int j=;j<x.updata_len();j++)
{
if(i+j>maxn-) continue;
sum.num[i+j]+=num[i]*x.num[j];
}
sum.carry_bit();
return sum;
} number operator*= (number x){
return *this=*this*x;
} number factor(){
number ans,t;
t.num[]=;
ans.num[]=;
for(;t<=*this;t.num[]+=,t.carry_bit())
ans*=t;
return ans;
} number division2(){
for(int i=maxn-;i>=;i--){
if(num[i]&&&i!=) num[i-]+=;
num[i]>>=;
}
return *this;
}
}; istream & operator>> (istream &in, number &obj)
{
string a;
in>>a;
if(a[]=='-'){
obj.fu=;
obj.len=a.size()-;
for(unsigned int i=;i<a.size()-;i++) obj.num[i]=a[a.size()-i-]-'';
}
else{
obj.len=a.size();
for(unsigned int i=;i<a.size();i++) obj.num[i]=a[a.size()-i-]-'';
}
if (!in) obj = number();
return in;
} ostream & operator<< (ostream &out, number &obj)
{
if(obj.fu) cout<<"-";
bool flag=;
for(int i=obj.len;i>;i--){
if(obj.num[i]) flag=;
if(obj.num[i]>) obj.carry_bit();
if(flag) out<<obj.num[i];
}
out<<obj.num[];
return out;
} number gcd_rec(number a,number b){
if(b.judge_zero()) return a;
return gcd_rec(b,a-b);
} number gcd(number a,number b){
if(a.judge_zero()) return a;
number t;
for(;;t=b,b=a-b,a=t)
if(b.judge_zero()) return a;
return a;
} number power(number a,number n){
number zero;
number c;c=;
for(;n>zero;n.division2(),a*=a) if(n.odd()) c*=a;
return c;
} int main()
{
freopen("gcd.in","r",stdin);
freopen("gcd.out","w",stdout);
number a,b,c;
cin>>a>>b;
c=gcd(a,b);
cout<<c;
return ;
}

折柳的高精度模板Code

更新日志

其实我是在写了300行以后才来写这篇博客的,所以之前的时间点就不计了吧!

(2019-11-05ago)

加法

进位

构造

比较

减法

退位

递归求gcd

非递归gcd

乘法

阶乘

iostream

除以2

判断奇偶

快速幂

……

细节实现

相信这里有许多我(以前)不会的c++语言用法吧。我把它们都记录下来了呢!

构造函数

当我们定义一个number时,由于可能是局部变量,我们就要先将其赋初值

但是number不是int,不是double,要是我们要赋初值的话,还得将其所有的变量(even arraies!)赋初值!

所以我为了在使用number时方便,在网上找了个东西叫做 构造函数

函数与结构体(或类,一下省略)同名,没有返回值(不是void!)

在新定义一个number时会自动调用

作用大概就是 赋初值 吧

(PS:还有个函数叫 析构函数,用于释放结构体内存时操作(例如:删除指针等),有兴趣可以去看看)

number(){
len=fu=;
memset(num,,sizeof(num));
}

但要是我们要给一个number赋初值怎么办?

一个即将退役的老OIer告诉我,再来一个构造函数,但是它是要传参的呗!

但是,由于我不会用,只好重载的=(赋值运算符)来赋初值。

number operator= (int x){//隐式转换(?)
fu=(x<);
num[]=abs(x);
if(x>) carry_bit();
if(x<-) back_space();
return *this;
}

也许以后我就会用了吧!

重载前缀自增自减运算符

本来我想到了自增自减有前缀和后缀之分,但是不知道该怎么打……

所以就先打了个不知道是哪种的operator+

number operator++ (){
num[]++;
if(num[]>) carry_bit();
return *this;
}

结果发现只有前缀才能用。

那么后缀的该怎么打呢?

重载后缀自增自减运算符

几番查找后,终于在《C++ Primer Plus》里面找到了

只要在()里加一个int即可

(原理不知)

number operator++ (int){
number save=*this;
++*this;
return save;
}

这里我甚至还偷懒地在后缀里用了前缀……本来就没错嘛!

重载赋值运算符(int转num高精度)

见 构造函数 末尾部分

number operator= (int x){//隐式转换
fu=(x<);
num[]=abs(x);
if(x>) carry_bit();
if(x<-) back_space();
return *this;
}

重载输入输出流运算符(友元)

首先我为了输入输出各自写了一个成员函数

void input(){
string a;
cin>>a;
if(a[]=='-'){
fu=;
len=a.size()-;
for(unsigned int i=;i<a.size()-;i++) num[i]=a[a.size()-i-]-'';
}
else{
len=a.size();
for(unsigned int i=;i<a.size();i++) num[i]=a[a.size()-i-]-'';
}
}
void output(){
if(fu) cout<<"-";
bool flag=;
for(int i=len;i>;i--){
if(num[i]) flag=;
if(num[i]>) carry_bit();
if(flag) putchar(num[i]+'');//putchar加速
}
putchar(num[]+'');
}

后来,我想:看看人家STL-string,都可以直接拿cin cout输入输出了,你怎么就不可以做到呢?

我又去网上,书中找了找怎么重载流运算符……

不想讲了,就是套模板,把之前写的那个input和output套进去就可以了嘛!

But,由于stream是一个已经封装好了的类,你也不能修改头文件中的内容,怎么办呢?

answer:用友元!它可以“打入敌人内部”进行一些操作!

友元函数声明(要放在结构体中!)

friend istream & operator>> (istream &in, number &obj);
friend ostream & operator<< (ostream &out, number &obj);

即 在正常的函数前加上friend即可

友元函数定义(要放在全局中!)

istream & operator>> (istream &in, number &obj)
{
string a;
in>>a;
if(a[]=='-'){
obj.fu=;
obj.len=a.size()-;
for(unsigned int i=;i<a.size()-;i++) obj.num[i]=a[a.size()-i-]-'';
}
else{
obj.len=a.size();
for(unsigned int i=;i<a.size();i++) obj.num[i]=a[a.size()-i-]-'';
}
if (!in) obj = number();
return in;
} ostream & operator<< (ostream &out, number &obj)
{
if(obj.fu) cout<<"-";
bool flag=;
for(int i=obj.len;i>;i--){
if(obj.num[i]) flag=;
if(obj.num[i]>) obj.carry_bit();
if(flag) out<<obj.num[i];
}
out<<obj.num[];
return out;
}

重载判断符运算符

那么多比较函数,我一下子那写的过来呢?

本来我都是没有operator这些比较运算符的,只用了一个int compare(number)就好了

PS:为什么返回值不是bool而是int呢?因为返回的信息可能不只有大于,小于,还会有等于呀!

int compare(number x){//2=    1> 0<
if(fu^x.fu){
if(fu) return ;
else return ;
}
for(int i=max(len,x.len);i>=;i--)
{
if(num[i]>x.num[i]) return !fu;//大于 (1)
if(num[i]<x.num[i]) return fu;//小于 (0)
}
return ;//相等
}

后来,我觉得这样十分的不直观,而且有时容易错,还是个成员函数,调用时是a.compare(b)这样的形式的……

所以我就把"<",">","<=",">=","==","!="都重载了!

Impression

现在的长度是有限的而且在枚举时也可能会有大量时间浪费

尽管已经引进了len和updata_len(),但是这两个玩意的作用还是较小,用法比较麻烦

希望能像STL的某些容器那样可自动改变大小,已经O(1)就可以知道number的位数

不知道为什么,一个number表达式不可以用cout<<输出?

就像

a,b为number时,cout<<(a+b);不可以;

但是

a,b为int时,cout<<(a+b);可以!

是因为operator<< 里的参数obj为引用吗?

除法(二分)

这个玩意还有存在许多许多可以更新&改进的地方,欢迎提建议!

高精度模板 支持各种运算 c++的更多相关文章

  1. 让ecshop模板支持php运算

    让ecshop模板支持php运算在 cls_template.php 底部加入函数: /** * 处理if标签 * * @access public * @param string $tag_args ...

  2. C++高精度模板

    原文地址:http://blog.csdn.net/wall_f/article/details/8373395 原文只附代码,没有解析,本文增加了一些对代码的解释. 请注意:本模板不涉及实数运算与负 ...

  3. [Template]高精度模板

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

  4. Tornado 模板支持“控制语句”和“表达语句”的表现形式

    Tornado 的模板支持“控制语句”和“表达语句”,控制语句是使用 {% 和 %} 包起来的 例如 {% if len(items) > 2 %}.表达语句是使用 {{ 和 }} 包起来的,例 ...

  5. ASP.NET MVC:多模板支持

    原文 http://www.cnblogs.com/happyframework/p/3224278.html 背景 准备写个博客练习一下WEB编程,有一个需求就是多模板支持,类似博客园的自定义模板一 ...

  6. MVC多模板支持

    参考: ASP.NET MVC:多模板支持

  7. jetty el表达式不支持三元运算

    在jetty跑web程序中不支持三元运算 要换一种格式写 这种代码在jsp页面用jetty跑起来是会报错的,然后调换一下顺序就可以了  或者在后面那个加个括号也可以 

  8. [note]高精度模板

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

  9. java 大数运算,高精度模板

    转自:https://blog.csdn.net/stffer/article/details/46382949 有修改 关于BigInteger类更详细的用法请移步官方文档 package prac ...

随机推荐

  1. ios---scrollview用法总结

    一.使用步骤: 1.添加子组件到scrollview //必要步骤 2.设置clipsToBounds来确定超出范围是否被剪裁 (默认yes) self.scrolltest.clipsToBound ...

  2. java web 各个文件夹命名原因

    今天突然被同学问然后就发现,自己有很多的疑问: (1) 为什么servlet的配置文件,命名为 web.xml , 内部是如何读取的,原因就是他内度的工作原理 (2) webINF Src 文件为什么 ...

  3. ROC 曲线

    Receiver Operating Characteristic (接收机操作特性曲线) 是以虚警率为横轴,以击中率为纵轴,长成如下模样: 所谓击中率(hit)是指将正样本判断为正样本的比例,而虚警 ...

  4. 实验11:EIGRP

    实验8-1:EIGRP 基本配置 实验目的通过本实验可以掌握:(1)在路由器上启动EIGRP 路由进程(2)启用参与路由协议的接口,并且通告网络(3)EIGRP 度量值的计算方法(4)可行距离(FD) ...

  5. reload重载配置文件的真相

    02检查配置文件语法也就是说在重载nginx配置文件之前,不是必须使用nginx -t检查语法 03修改配置文件,新开启端口,比如443,所以需要打开新的监听端口 04使用新配置启动新的worker子 ...

  6. 死磕mysql(3)

    花了一个晚上得出的结论,autocommit=1是不是立刻提交,autocommit=0是没有写入数据库的关闭数据,除非遇到commit和rollback........把自己给逗了关闭数据库发现数据 ...

  7. 遍历CSDN博客

    --http://blog.csdn.net/leixiaohua1020/article/list/14?viewmode=contents function saveData(data) loca ...

  8. ImageButton去边框&Button或者ImageButton的背景透明

    在ImageButton中载入图片后,很多人会觉得有图片周围的白边会影响到美观,其实解决这个问题有两种方法 一种方法是将ImageButton的背景改为所需要的图片.如:android:backgro ...

  9. PostMan向企业微信机器人传送数据测试

    1 在企业微信中创建机器人  获取:webhook 地址 2.在Postman软件中创建Post文件 Post文件请求类型要与机器人所接受的类型一致.Get  或者 Post Url地址为上面webh ...

  10. python 更改pip源

    用pip安装依赖包时默认访问https://pypi.Python.org/simple/,但是经常出现不稳定以及访问速度非常慢的情况,国内厂商提供的pipy镜像目前可用的有: http://pypi ...