以顺序表存储的大整数运算
来源:互联网 发布:淘宝保健品规则 编辑:程序博客网 时间:2024/05/16 18:11
大整数运算的实现原理
写一个BigInt(大整数)类,其中数据成员是一个顺序表,用来保存大整数.其方法是将数的每一位数(0~9中的一个)存放在每一个节点中,高位存放在高下标,低位存放在低下标.注意:实现时下标是从1开始的.类中的运算如Add(), Sub()等全用友元函数来实现.类中还有一些辅助的函数,如push_back(), push_front()等是用BigInt的数据成员调用了顺序表中的函数.还有一些其他函数在代码中有所说明.
顺序表中提供了一些顺序表的基本操作,构造,插入,以及插入时容量不足的处理函数等.
代码
seqlist.h
#ifndef _SEQLIST_H#define _SEQLIST_H#include"utili.h"template<typename Type>class SeqList{public: SeqList(size_t sz = DEFAULT_SIZE) { capacity = sz > DEFAULT_SIZE ? sz : DEFAULT_SIZE; base = new Type[capacity + 1]; //空出一个0下标 memset(base, 0, sizeof(Type) * (capacity+1)); size = 0; } SeqList& operator=(const SeqList &sql) { if (this != &sql) { Type *new_base = new Type[sizeof(Type) * sql.Capacity()+1]; //申请新空间 memset(new_base, 0, sizeof(Type) * (sql.Capacity()+1)); //赋初始值 for (ulong i = 1; i <= sql.Size(); i++) //赋值数据 new_base[i] = sql.base[i]; delete []base; //释放旧空间 base = new_base; //指向新空间 size = sql.Size(); capacity = sql.Capacity(); } return *this; } ~SeqList() { delete []base; base = NULL; capacity = size = 0; }public: bool isfull()const{return size >= capacity;} bool isempty()const{return size == 0;}public: bool push_back(const Type &x) {//尾部插入 if(isfull() && !Inc()) //顺序不能改变 return false; base[++size] = x; return true; } bool push_front(const Type &x) {//头部插入 if (isfull() && !Inc()) return false; size++; //移动数据并插入 for (ulong i = size-1; i >= 1; i--) base[i+1] = base[i]; base[1] = x; return true; }public: bool pop_back() {//尾部删除 if (isempty()) return false; base[size--] = 0; } bool pop_front(); void reset() {//顺序表清空 memset(base, 0, sizeof(Type) * (capacity+1)); size = 0; }public: ulong Size() { return size; } ulong Size()const { return size; } ulong Capacity() { return capacity; } ulong Capacity()const { return capacity; }public: Type& operator[](ulong pos) { return base[pos]; } Type& operator[](ulong pos)const { return base[pos]; }protected: bool Inc() {//空间不足时处理函数 Type *new_base = new Type[capacity + INC_SIZE + 1]; //申请新空间 if (new_base == NULL) return false; memset(new_base, 0, sizeof(Type)*(capacity+INC_SIZE+1)); //赋值0 memcpy(new_base, base, sizeof(Type)*(capacity+1)); //数据移动复制 capacity += INC_SIZE; //容量增加INC_SIZE delete []base; //释放旧空间 base = new_base; //base指向新的空间 return true; }private: enum{DEFAULT_SIZE=20, INC_SIZE=10}; //默认大小,增长长度 Type *base; //指向数组空间的指针 ulong capacity; //容量 ulong size; //顺序表大小};#endif
bigint.h
#include "seqlist.h"class BigInt{public: BigInt(); BigInt(int x); BigInt& operator=(const BigInt &bt);public: void LoadData(int sz); //随机加载一个长度sz的整数 void PrintData()const; //输出整数 ulong size()const; //返回整数的位数 void reset(); //将整数置为空public: bool push_back(uchar x); //从后面插入一位数 bool push_front(uchar x); //从前面插入一位数 bool pop_back(); //从后面删除一位数public: uchar& operator[](ulong pos); //取出pos下标的数字 uchar& operator[](ulong pos)const;public: bool operator>=(const BigInt &bt)const; bool operator<(const BigInt &bt)const; bool operator<=(const BigInt &bt)const; bool operator>(const BigInt &bt)const; bool operator==(const BigInt &bt)const; bool operator!=(const BigInt &bt)const;public: BigInt& operator++(); BigInt operator++(int);public: BigInt operator-(const BigInt &bt); BigInt& operator+=(const BigInt &bt); BigInt& operator*=(const BigInt &bt);public: //大整数bt1运算bt2,结果保存在bt中 friend void Add(BigInt &bt, const BigInt &bt1, const BigInt &bt2); friend void Sub(BigInt &bt, const BigInt &bt1, const BigInt &bt2); friend void Mul(BigInt &bt, const BigInt &bt1, const BigInt &bt2); friend void Div(BigInt &bt, const BigInt &bt1, const BigInt &bt2); friend void Mod(BigInt &bt, const BigInt &bt1, const BigInt &bt2); friend void Square(BigInt &bt, const BigInt &bt1); friend void Power(BigInt &bt, const BigInt &bt1, long n); friend void Power(BigInt &bt, const BigInt &bt1, const BigInt &bt2);private: SeqList<uchar> big; //用顺序表存放大数};
bigint.cpp
#include "bigint.h"#include <cmath>//Add(),Sub(),Mul()调用的函数,用来计算数的一位的结果uchar AddItem(uchar a, uchar b, uchar &sign);uchar SubItem(uchar a, uchar b, uchar &sign);uchar MulItem(uchar a, uchar b, uchar &sign);BigInt::BigInt(){}BigInt::BigInt(int x){ if (x == 0) { push_back(0); return; } while (x > 0) { push_back(x % 10); x /= 10; }}BigInt& BigInt::operator=(const BigInt &bt){ if (this != &bt) { (*this).big = bt.big; } return *this;}///////////////////////////////////////////////////////////////void BigInt::LoadData(int sz){//按位数置一个随机数 srand(time(NULL)); for (ulong i = 0; i < sz; i++) { push_back(rand() % 10); }}void BigInt::PrintData()const{//输出数 for (ulong i = size(); i >= 1; i--) { cout << (int)big[i]; } cout << endl;}//////////////////////////////////////////////////////////调用了seqlist的成员函数bool BigInt::push_back(uchar x){ return big.push_back(x);}bool BigInt::push_front(uchar x){ return big.push_front(x);}bool BigInt::pop_back(){ big.pop_back();}void BigInt::reset(){ big.reset();}ulong BigInt::size()const{ return big.Size();}////////////////////////////////////////////////////////uchar& BigInt::operator[](ulong pos){ return big[pos];}uchar& BigInt::operator[](ulong pos)const{ return big[pos];}///////////////////////////////////////////////////////////bool BigInt::operator>=(const BigInt &bt)const{ if (size() > bt.size()) return true; else if (size() < bt.size()) return false; ulong i; i = size(); while (i >= 1) { if ((*this)[i] > bt[i]) return true; else if((*this)[i] < bt[i]) return false; i--; } return true;}bool BigInt::operator<(const BigInt &bt)const{ return !((*this) >= bt);}bool BigInt::operator==(const BigInt &bt)const{ if (size() != bt.size()) return false; ulong i = size(); while (i >= 1) { if ((*this)[i] != bt[i]) return false; --i; } return true; }bool BigInt::operator!=(const BigInt &bt)const{ return !((*this)==bt);}bool BigInt::operator<=(const BigInt &bt)const{ return ((*this)<bt || (*this)==bt);}//////////////////////////////////////////////////////BigInt& BigInt::operator++(){ ulong i = 1; uchar sign = 1; while (sign == 1 && i <= size()) { (*this)[i] = AddItem((*this)[i], 0, sign); ++i; } if (sign == 1) push_back(sign); return *this;}BigInt BigInt::operator++(int){ BigInt tmp = *this; ++*this; return tmp;}BigInt& BigInt::operator+=(const BigInt &bt){ ulong i = 1; ulong j = 1; uchar sign = 0; while(i<=size() && j<=bt.size()) { (*this)[i] = AddItem((*this)[i], bt[j], sign); ++i; ++j; } while(sign>0 && i<=size()) {//*this没有加完 (*this)[i] = AddItem((*this)[i], 0, sign); ++i; } while(j <= bt.size()) {//bt没有加完的情况,之所以和上一个while循环内部有所不同, //是为了保证*this的size的正确性 uchar sum = AddItem(0, bt[j], sign); push_back(sum); ++j; } if(sign > 0) push_back(sign); return *this;}BigInt& BigInt::operator*=(const BigInt &bt){ BigInt tmp; Mul(tmp, (*this), bt); (*this) = tmp; return *this;}BigInt BigInt::operator-(const BigInt &bt){ assert(*this >= bt); BigInt tmp; Sub(tmp, *this, bt); return tmp;}///////////////////////////////////////////////////////////void Add(BigInt &bt, const BigInt &bt1, const BigInt &bt2){ bt.reset(); ulong i = 1; ulong j = 1; uchar sign = 0; uchar sum; while(i<=bt1.size() && j<=bt2.size()) { sum = AddItem(bt1[i++], bt2[j++], sign); bt.push_back(sum); } while(i <= bt1.size()) {//bt1位数 > bt2位数 sum = AddItem(bt1[i++], 0, sign); bt.push_back(sum); } while(j <= bt2.size()) {//bt2位数 > bt1位数 sum = AddItem(0, bt2[j++], sign); bt.push_back(sum); } if(sign > 0) //最高位的进位 bt.push_back(sign);}void Sub(BigInt &bt, const BigInt &bt1, const BigInt &bt2){ assert(bt1 >= bt2); bt.reset(); if(bt1 == bt2) { bt.push_back(0); return; } ulong i = 1; ulong j = 1; uchar sign = 0; uchar sub; while(i<=bt1.size() && j<=bt2.size()) { sub = SubItem(bt1[i++], bt2[j++], sign); bt.push_back(sub); } while(i<=bt1.size()) { sub = SubItem(bt1[i++], 0, sign); bt.push_back(sub); } for (ulong k = bt.size(); k >= 1; k--) {//除去前置的0 if (bt[k] == 0) bt.pop_back(); else break; }}#if 0void Mul(BigInt &bt, const BigInt &bt1, const BigInt &bt2){//效率低的版本 for (BigInt i = 0; i < bt2; ++i) {//bt2个bt1加到bt上 bt += bt1; }}#endifvoid Mul(BigInt &bt, const BigInt &bt1, const BigInt &bt2){ bt.reset(); if (bt1 == 0 || bt2 == 0) {//有一个数为0,直接返回0 bt.push_back(0); return; } uchar sign = 0; for (ulong i = 1; i <= bt2.size(); i++) { BigInt mul; //保存bt1和bt2每一位的乘积 for (ulong j = 1; j <= bt1.size(); j++) { uchar x = MulItem(bt2[i], bt1[j], sign); mul.push_back(x); } if (sign > 0) { mul.push_back(sign); sign = 0; } //bt += mul * pow(10, i-1); for (ulong k = 1; k < i; k++) mul.push_front(0); //提升mul bt += mul; }}void Div(BigInt &bt, const BigInt &bt1, const BigInt &bt2){ assert(bt2 != 0); //除数不能为0 bt.reset(); if (bt1 < bt2) //若bt1 < bt2, 则返回0 { bt.push_back(0); return; } BigInt tmp; //被除数 bool on_off = false; //定义一个开关,用于排除前置的0值 for (ulong i = bt1.size(); i >= 1; i--) //从最高位开始 { tmp.push_front(bt1[i]); uchar shang = 0; //保存商值 while (tmp >= bt2 && tmp - bt2 >= 0) //1 { shang++; //tmp -= bt2; tmp = tmp - bt2; } if (tmp == 0) tmp.reset(); if (shang != 0) { bt.push_front(shang); on_off = true; } else if (shang == 0 && on_off) bt.push_front(shang); }}///////////////////////////////////////////////////////////////void Square(BigInt &bt, const BigInt &bt1){//bt ^ 2 Mul(bt, bt1, bt1);}void Power(BigInt &bt, const BigInt &bt1, long n){//bt1 ^ n if (bt1 == 0) { bt = 0; return; } if (n == 0) { bt = 1; return; } bt = 1; for (long i = 0; i < n; i++) {//n个bt1相乘 bt *= bt1; }}void Power(BigInt &bt, const BigInt &bt1, const BigInt &bt2){//bt1 ^ bt2 if (bt1 == 0) { bt = 0; return; } if (bt2 == 0) { bt = 1; return; } bt = 1; for (BigInt i = 0; i < bt2; ++i) {//bt2个bt1相乘 bt *= bt1; }}void Mod(BigInt &bt, const BigInt &bt1, const BigInt &bt2){//bt1 % bt2 if (bt1 <= bt2) { bt = 0; return; } BigInt cnt; //bt1中有cnt个bt2 BigInt tmp; Div(cnt, bt1, bt2); //bt1减去cnt个bt2, 结果即为余数 Mul(tmp, bt2, cnt); Sub(bt, bt1, tmp);}///////////////////////////////////////////////////////////////uchar AddItem(uchar a, uchar b, uchar &sign){//计算一位数加法 uchar sum = a + b + sign;#if 0 if (sum >= 10) { sum -= 10; sign = 1; } else sign = 0;#endif sign = sum / 10; sum %= 10; return sum;}uchar SubItem(uchar a, uchar b, uchar &sign){//一位数相减 uchar sub; if (a - sign >= b) {//足够减 sub = a - b - sign; sign = 0; } else {//借位相减 sub = a + 10 - b - sign; sign = 1; } return sub;}uchar MulItem(uchar a, uchar b, uchar &sign){//一位数相乘 uchar mul = a * b + sign; sign = mul / 10; mul %= 10; return mul;}
utili.h
#ifndef __UTILI_H#define __UTILI_H#include <iostream>#include <assert.h>#include <string.h>#include <stdlib.h>using namespace std;typedef unsigned long ulong;typedef unsigned char uchar;#endif
Makefile
bigmain : bigmain.o bigint.o g++ -o bigmain bigmain.o bigint.obigmain.o : bigmain.cpp g++ -o bigmain.o -c bigmain.cpp -gbigint.o : bigint.cpp g++ -o bigint.o -c bigint.cpp -g.PHONY:cleanclean: rm *.o bigmain
测试
测试很简单,只要定义BigInt对象,并调用友元函数即可.
#include "unistd.h"#include "bigint.h"int main(){ BigInt bt; BigInt bt1, bt2; bt1.LoadData(10); bt1.PrintData(); sleep(1); bt2.LoadData(10); bt2.PrintData(); //Add(bt, bt1, bt2); //Sub(bt, bt1, bt2); //Mul(bt, bt1, bt2); //Div(bt, bt1, bt2); //Square(bt, bt1); //Power(bt, bt1, 100); //Power(bt, bt1, bt2); Mod(bt, bt1, bt2); bt.PrintData(); return 0;}
0 0
- 以顺序表存储的大整数运算
- 大整数存储和运算
- 顺序表实现集合及大整数运算
- 大整数的存储
- 大整数的存储
- 大整数的运算实现
- 大整数的乘法运算
- 大整数的乘法运算
- 大整数的加法运算
- 大整数的乘法运算
- 大整数的加减乘除运算
- 大整数存储及运算——求100的阶乘
- 数据结构--数组和广义表--以行逻辑链接的顺序表为存储结构的矩阵的基本运算(求矩阵乘积)
- 用数组存储大整数,实现大整数的加法
- java是实现的大整数运算!
- 一个大整数运算的类
- 大整数的乘法与阶乘运算
- 大整数的加减乘运算
- 我的Map实现
- JAVA MAP相关
- 启动MongoDB时cmd窗口一闪而过
- Java 程序员必须收藏的资源大全
- 【转载】CSDN-markdown语法之如何使用LaTeX语法编写数学公式
- 以顺序表存储的大整数运算
- 走进AndroidStudio下的NDK
- Java布局管理器setLayout()
- iOS7兼容自定义带动画的AlertViewController
- js如何实现广告在pc端显示,移动端不显示.直让广告在点上是显示,手机上不显示代码
- 【转载】MarkDown 图片大小问题
- java中使用POI(HSSF)导出excel表格
- 每天一条linux命令 ---cat命令
- C++中二维数组的动态创建与处理