我是靠谱客的博主 帅气山水,最近开发中收集的这篇文章主要介绍C++实现二进制快速加减法,分治策略之整数位乘(一)前言一、自己写的代码二.官方代码:(二进制加法)总结,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
前言
以下是二进制整数位乘中的二进制加法的代码,包含自己尝试与答案分析,虽然二进制加法实现起来非常容易,但是一般要求使用分治实现二进制整数位乘的算法题位数都十分巨大,因此对二进制加法的实现速度也有一定要求。
一、自己写的代码
先看代码,后评价
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
using namespace std;
struct BigBinary //用于存储二进制位数
{
std::vector<int> x; // 由低位到高位保存二进制位
bool neg; // 标记数的正负,true为负
void Init(){x.clear(); neg = false;}
BigBinary(){Init();} //初始化
void Print() //打印
{
if(neg && !x.empty()) printf("-");
for(int i = x.size() - 1; i >= 0; i --)
printf("%d", x[i]);
if(x.empty()) printf("0");
printf("n");
}
};
BigBinary Add(BigBinary &a, BigBinary &b)
{
// TODO: 返回 a + b 的结果,小心两数异号情况
if(a.neg!=b.neg)//如果仅需要实现同符号加法请把if和其区域都删去
{
if(a.neg)//如果符号不同就转移至减法,并且保证是前减后减法下一篇文章会讲解
{
a.neg=!a.neg;
return Minus(b,a);
}
b.neg=!b.neg;
return Minus(a,b);
}
BigBinary c;
c.Init();
int k=0; //用于保存是否有进位的情况(k不是0就是1)
c.neg=a.neg;
int i=0,j=0,a_long=a.x.size(),b_long=b.x.size(),lin;
while(i!=a_long&&j!=b_long) //模拟二进制加法的计算过程
{
lin=a.x[i]+b.x[j];
if(lin==0) //lin用于保存计算结果
{
if(k)
{
lin++; //若结果为0且k为1
k--;
}
c.x.push_back(lin);
}else if(lin==1)
{
if(k) //这里k不变,lin归0,因为进位
lin--;
c.x.push_back(lin);
}else //lin==2时
{
lin=0;
if(k)
lin++;
else
k++;
c.x.push_back(lin);
}
i++;
j++;
}
while(i!=a_long) //当b被加完时
{
if(k) //如果还存在进位
{
if(a.x[i])
{
c.x.push_back(0);
i++;
}else
{
c.x.push_back(1);
i++;
k--;
}
}else
{
c.x.push_back(a.x[i]);
i++;
}
}
while(j!=b_long) //同理
{
if(k)
{
if(b.x[j])
{
c.x.push_back(0);
j++;
}else
{
c.x.push_back(1);
j++;
k--;
}
}else
{
c.x.push_back(b.x[j]);
j++;
}
}
if(k) //处理二进制边界进位,这里是if而不是while
//因为二进制相加最多变化位数较多的那位中的一位(二进制之间的关系比如111+111=1110)
c.x.push_back(1);
while(!c.x.empty() && c.x.back()==0)
c.x.pop_back();
return c;
}
char lin[100005];
int main(void)
{
BigBinary a,b,c;
a.Init();
b.Init();
scanf("%s",lin);
for(int i=strlen(lin)-1;i>=0; i--)
{
a.x.push_back(lin[i]=='1');
}
scanf("%s",lin);
for(int i=strlen(lin)-1;i>=0; i--)
{
b.x.push_back(lin[i]=='1');
}
c=Add(a,b);
c.Print();
}
代码分析:
代码的运行速度勉强达标,题目实现不难,模拟二进制的加法就可以很流程的写出来。但是代码流畅度不够,太繁琐且太注重过程,没有面对对象,并且没有注重二进制加法本身特性。
二.官方代码:(二进制加法)
代码如下:
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
using namespace std;
struct BigBinary //用于存储二进制位数
{
std::vector<int> x; // 由低位到高位保存二进制位
bool neg; // 标记数的正负,true为负
void Init(){x.clear(); neg = false;}
BigBinary(){Init();} //初始化
unsigned size(){return x.size();}//注意,此处是为了方便直接得到vector大小
void Print() //打印
{
if(neg && !x.empty()) printf("-");
for(int i = x.size() - 1; i >= 0; i --)
printf("%d", x[i]);
if(x.empty()) printf("0");
printf("n");
}
};
bool AbsAgB(BigBinary &a, BigBinary &b)//注意这里时比较a和b的大小
{
if(a.size() > b.size()) return true;
if(b.size() > a.size()) return false;
for(int i = a.size() - 1; i >= 0; i --)
{
if(a.x[i] > b.x[i]) return true;
if(b.x[i] > a.x[i]) return false;
}
return true;
}
BigBinary Add(BigBinary &a, BigBinary &b)
{
BigBinary c;
if(a.neg != b.neg)//如果仅需要实现同符号加法请把if和其区域都删去,减法下一篇再讲
{
if(AbsAgB(a, b)) //为了让大的减去小的,方便确认结果符号
{
b.neg ^= 1;
c = Minus(a, b);
b.neg ^= 1; //因为是引用,所以要转回来,这里是为了改变符号,
}
else
{
a.neg ^= 1;
c = Minus(b, a);
a.neg ^= 1;
}
return c;
}
if(a.size() < b.size()) return Add(b, a); //为了让位多的在前,可以缩短代码量
c.x = a.x; //将a的vector赋予c
for(int i = 0; i < b.size(); i ++) c.x[i] += b.x[i]; //c.x[i]最大的是2
int cur = 0; //记录进位
for(int i = 0; i < c.size(); i ++)
{
c.x[i] += cur; //max(c.x[i])=3
cur = c.x[i] >> 1; //右移整数和整数/2结果相同,cur最大为1
c.x[i] &= 1; //这里相当于判断奇偶,偶为0,奇数为1
}
for(; cur; cur >>= 1) c.x.push_back(cur & 1); //用if效果一致
c.neg = a.neg;
while(!c.x.empty() && c.x.back() == 0) c.x.pop_back();
return c;
}
char lin[100005];
int main(void)
{
BigBinary a,b,c;
a.Init();
b.Init();
scanf("%s",lin);
for(int i=strlen(lin)-1;i>=0; i--)
{
a.x.push_back(lin[i]=='1');
}
scanf("%s",lin);
for(int i=strlen(lin)-1;i>=0; i--)
{
b.x.push_back(lin[i]=='1');
}
c=Add(a,b);
c.Print();
}
代码分析:
整体方面将二进制加法分为三大块,第一部分是全部相加,不统计进位;第二部分是处理二进制数的进位;最后一部分是处理边缘。并且当中利用了很多小细节进行加速,比如 c.x[i] &= 1; 判断奇偶,还有利用右移1位(相当于除以2)来加速。最大的亮点就是不像自己写的代码那样按部就班,注重分块,同时非常简洁条理清晰。
总结
官方写得好,如果发现代码出现bug或有相关疑问都可以在评论区和我讨论。
最后
以上就是帅气山水为你收集整理的C++实现二进制快速加减法,分治策略之整数位乘(一)前言一、自己写的代码二.官方代码:(二进制加法)总结的全部内容,希望文章能够帮你解决C++实现二进制快速加减法,分治策略之整数位乘(一)前言一、自己写的代码二.官方代码:(二进制加法)总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复