求教代码 算法的总体设计思想,代码大致解释,万分感谢

lq1609 2009-05-31 11:50:55
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cassert>
using namespace std;

class SuperNumber {
public:
SuperNumber() {
memset(data, 0, MAX_SIZE);
high = 0;
}
// 一般整型到SuperNumber的转换,该版本中不支持负数
SuperNumber(unsigned long l) {
memset(data, 0, MAX_SIZE);
high = 0;
while(l) {
data[++high] = l % 10;
l /= 10;
}
}
// str为字符串形式表示的十进制数
SuperNumber(const char* str) {
assert(str != NULL);
high = strlen(str);
for(int i = high, j = 0; i >= 1; i--, j++) {
data[i] = str[j] - '0';
}
}
SuperNumber(const SuperNumber& s) {
memcpy(data, s.data, MAX_SIZE);
high = s.high;
}
operator const char*() const {
return toString(10);
}
SuperNumber& operator=(const SuperNumber& s) {
if(this != &s) {
memcpy(data, s.data, MAX_SIZE);
high = s.high;
}
return *this;
}
...全文
132 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
wesweeky 2009-06-01
  • 打赏
  • 举报
回复
lz在干吗
lq1609 2009-05-31
  • 打赏
  • 举报
回复
// 测试四则运算
void testOp() {
SuperNumber s, t;
int i;
cout << "\ntest operation\n";
nPass = nFail = 0;

s = 54;
t = 789;
cout << "test 54 * 789\n";
test(strcmp(s*t, "42606")==0);

cout << "test 2^128\n";
for(i = 1, s = 1; i <= 128; i++)
s = s * 2;
test(strcmp(s, "340282366920938463463374607431768211456")==0);

s.setToStr("170141183460469231731687303715884105757");
t.setToStr("170141183460469231731687303715884105773");
cout << "test 170141183460469231731687303715884105757 * "
"170141183460469231731687303715884105773\n";
test(strcmp(s*t,
"28948022309329048855892746252171976975907943742484864"
"158009256476953706235161")==0);
cout << s*t << endl;

cout << "test " << s << " * 1\n";
test(strcmp(s * SuperNumber("1"),
"170141183460469231731687303715884105757")==0);
cout << "test " << s << " * 0\n";
test(strcmp(s * SuperNumber("0"), "0")==0);

s.setToStr("99999999999999999999");
t.setToStr("999999999999999999999");
cout << "test 99999999999999999999 * 9999999999999999999999\n";
test(strcmp(s*t,
"99999999999999999998900000000000000000001")==0);
cout << s*t << endl;

s.setToStr("7368");
t.setToStr("89");
cout << "test 7368/89\n";
test(strcmp(s/t, "82")==0);
test(strcmp(s%t, "70")==0);

s.setToStr("100");
t.setToStr("89");
cout << "test 100/89\n";
test(strcmp(s/t, "1")==0);
test(strcmp(s%t, "11")==0);

s.setToStr("28948022309329048855892746252171976975907943742484864"
"158009256476953706235161");
t.setToStr("170141183460469231731687303715884105757");
cout << "test 28948022309329048855892746252171976975907943742484864"
"158009256476953706235161 / 170141183460469231731687303715884105757\n";
test(strcmp(s/t,
"170141183460469231731687303715884105773")==0);

cout << s / t << endl;


s.setToStr("11");
cout << "test 11^7 mod 17\n";
test(strcmp(s.power_mod(7, 17), "3")==0);

s.setToStr("1520");
cout << "test 1520^13 mod 2537\n";
test(strcmp(s.power_mod(13, 2537), "95")==0);

s.setToStr("16");
cout << "test 16^15 mod 4731\n";
test(strcmp(s.power_mod(15, 4731), "4339")==0);


s.setToStr("170141183460469231731687303715884105757");
t.setToStr("170141183460469231731687303715884106309");
cout << "test " << s << "\n ^ 37 % " << t << endl;
test(strcmp(s.power_mod(37, t),
"83985297447338215630640388629247868934")==0);

cout << "test " << s << "\n ^ 16329 % " << t << endl;
cout << s.power_mod(16329, t) << endl;

cout << "pass :" << nPass << "\t\t" << "fail :" << nFail << endl;
}
lq1609 2009-05-31
  • 打赏
  • 举报
回复
//测试
class SuperNumberTest {
public:
void run() {
testTransForm();
testOp();
testSub();
testCmp();
}
// 测试不同类型间的相互转换
void testTransForm() {
nPass = nFail = 0;
cout << "\ntestTransForm\n";

s.setToStr("17828");
cout << "test 17828\n";
test(strcmp(s, "17828")==0);
test(strcmp(s.toString(16),"45A4")==0);
test(strcmp(s.toString(2), "100010110100100")==0);
test(strcmp(s.toString(8), "42644")==0);

s.setToStr("8809810792117466628");
cout << "test 8809810792117466628\n";
test(strcmp(s, "8809810792117466628")==0);
test(strcmp(s.toString(16), "7A42BC3D32907604")==0);
test(strcmp(s.toString(2),
"111101001000010101111000011110100110010100100000111011000000100")==0);
test(strcmp(s.toString(8), "751025703646244073004")==0);

s.setToStr("170141183460469231731687303715884105757");
cout << "test 170141183460469231731687303715884105757\n";
test(strcmp(s, "170141183460469231731687303715884105757")==0);
test(strcmp(s.toString(16), "8000000000000000000000000000001D")==0);
test(strcmp(s.toString(2),
"10000000000000000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000000011101")==0);
test(strcmp(s.toString(8),
"2000000000000000000000000000000000000000035")==0);

s = 100;
cout << "test s=100\n";
test(strcmp(s, "100")==0);

SuperNumber s1(s);
cout << "test s1(s): copy constructor\n";
test(strcmp(s1, "100")==0);

SuperNumber s2;
s2 = s;
cout << "test s2 = s: operator=\n";
test(strcmp(s2, "100")==0);

cout << "pass :" << nPass << "\t\t" << "fail :" << nFail << endl;
}
lq1609 2009-05-31
  • 打赏
  • 举报
回复
// 大数模幂算法,很简单的自然算法,即将指数分解为二进制,换句
// 更简单的话来说,就是不断地找平方模幂,而不是全部乘方后再
// 做一次最终的模运算
// a.power_mod(p, n)计算a^p mod n
SuperNumber power_mod(int power, SuperNumber n) const {
SuperNumber c("1"), t(*this);

while(power) {
if(power % 2) {
c = c * t % n;
power -= 1;
} else {
t = t * t % n;
power /= 2;
}
}

return c%n;
}

bool operator>=(const SuperNumber& s) const {
if(high == s.high) {
int k = high;
while(data[k] == s.data[k] && k >= 1)k--;
if(k < 1) return true; // equal
return data[k] > s.data[k];
} else if(high > s.high) return true;
return false;
}

bool operator<(const SuperNumber& s) const {
return !(*this >= s);
}

// 从十进制表示的最高位开始数起,数到第i位,从第i位开始截取连续
// 的c位数字出来组成一个新的数。例如:数据是12345678925698,则
// sub(3, 5)返回数字34567,如果数字不够取,例如在34567上运行
// sub(3, 5),因为34567从高位数起第3个数字是5,剩下的数字是567,
// 最多只有三个,不够取要求的5个,这个时候返回567,不报错。
SuperNumber sub(int i, int c) const {
SuperNumber ret;
assert(high >= i); // 保证可截取

i = high - i + 1; // 从高位数起的第i个数位的下标
if(i >= c) {
ret.high = c;
while(c >= 1) ret.data[c--] = data[i--];
} else {
ret.high = i;
while(i >= 1) {
ret.data[i] = data[i];
i--;
}
}
// 过滤前导0
while(ret.data[ret.high] == 0) ret.high--;
return ret;
}

// I/O
friend istream& operator>>(istream& in, SuperNumber& s) {
char t[256];
in >> t;
s.setToStr(t);
return in;
}
friend ostream& operator<<(ostream& out, const SuperNumber& s) {
return out << s.toString(10);
}
private:
enum {MAX_SIZE=256}; // 最大十进制位数
// 须注意,使用data[0]存储最高位所在下标是自己的一点小聪明,后来在
// 调试的时候发现这是一个极大的错误,不过对于此题目来说可以应付
char data[MAX_SIZE]; // 数据的内部表示,字符串形式的十进制
// 其中data[0]存储最高位所在下标,data[1]
// 存储数据的最低位,也就是个位
int high;
};
coverallwangp 2009-05-31
  • 打赏
  • 举报
回复
晕,好长的代码,帮顶了
lq1609 2009-05-31
  • 打赏
  • 举报
回复
void doDivide(const SuperNumber& dest, SuperNumber& Q, SuperNumber& R) const {
int i, j, t;

Q.reset();
Q.high = high - dest.high + 1; // 商的初始位数
R = *this; // 余数初始实为被除数
t = dest.high;
// 判断除法是否结束
while(R >= dest) {
// 循环相减进行试除
while(dest >= R.sub(1, t)) {
Q.data[Q.high--] = 0;
++t;
}
while(R.sub(1, t) >= dest) {
// i为相减时被除数最低下标,j为除数最低下标
for(i=R.high-t+1,j=1; j<=dest.high; i++,j++) {
R.data[i] -= dest.data[j];
if(R.data[i] < 0) {
R.data[i] += 10;
R.data[i+1] -= 1;
}
}
while(R.data[i] < 0 && i <= R.high) {
R.data[i] += 10;
R.data[i+1] -= 1;
++i;
}
Q.data[Q.high] += 1;
}
// 一次试除结束,更新商的最高位下标
Q.high -= 1;
// 更新被除数的最高位下标
while(R.data[R.high] == 0) {
R.high--;
t--;
}
t+=1; // 下一位被除数
}

Q.high = high - dest.high + 1;
while(Q.data[Q.high] == 0) Q.high -= 1;
R.high = high;
while(R.data[R.high] == 0) R.high -= 1;
}

lq1609 2009-05-31
  • 打赏
  • 举报
回复
// 乘法
SuperNumber operator*(const SuperNumber& s) const {
SuperNumber result; // default set to 0
int i, j;

// 相乘
for(i = 1; i <= high; i++) {
for(j = 1; j <= s.high; j++) {
int k = data[i] * s.data[j] + result.data[i+j-1];
result.data[i+j-1] = k % 10;
result.data[i+j] += k / 10;
}
}
// 进位
for(i = 1; i < MAX_SIZE - 1; i++) {
if(result.data[i] >= 10) {
result.data[i+1] += result.data[i] / 10;
result.data[i] %= 10;
}
}
// 确定最高位
for(i = MAX_SIZE-1; i >= 1 && result.data[i] == 0; i--);
result.high = i;

return result;
}

// 除法,内部调用doDivide来实现
SuperNumber operator/(const SuperNumber& s) const {
SuperNumber q, r;
doDivide(s, q, r);
return q;
}
// 模运算,内部调用doDivide来实现
SuperNumber operator%(const SuperNumber& s) const {
SuperNumber q, r;
doDivide(s, q, r);
return r;
}

// 除法运算,一次除法运算中同时得到商和余数,运算符/和%的重载
// 内部会调用这个函数,dest为除数,Q为商,R为余数,算法使用试除法
lq1609 2009-05-31
  • 打赏
  • 举报
回复
// 将数据置为0
void reset() {
memset(data, 0, MAX_SIZE);
high = 0;
}

// str为字符串形式表示的十进制数
void setToStr(const char* str) {
assert(str != NULL);
high = strlen(str);
for(int i = high, j = 0; i >= 1; i--, j++) {
data[i] = str[j] - '0';
}
}
// 将数据转换成以base指定的进制的字符串形式,默认为十进制
const char* toString(int base = 10) const {
static char buf[MAX_SIZE];
const char table[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

if(high == 0) return "0";

assert(base >= 2); // 指定的进制应该不小于2

// 进制转换
buf[MAX_SIZE-1] = '\0';
int begin = MAX_SIZE-1;
char temp[MAX_SIZE];
memcpy(temp, data, MAX_SIZE);
while(1) {
// 找最高位的起始位置
int h = high;
while(temp[h] == 0 && h >= 1) h--;
if(h == 0) break;

// 除基取余
int t = 0;
while(h >= 1) {
t = t * 10 + temp[h];
temp[h] = t / base;
t = t % base;
h--;
}
buf[--begin] = table[t];
}

return buf+begin;
}

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧