您的位置:首页 > 其它

LychrelNumber实现V1.0

2016-06-13 00:00 393 查看
一、代码

1.main.cpp

#include <iostream>

using namespace std;

#include "BigNumber.h"

#define MAX_RANGE 1000
#define TIME 10000

#define UNKNOWN -1
#define YES 1

CBigNumber next[TIME+5] = {0};

void init();
int caculate(int number);
void result(int number, int ret);
void setAllInNextTable(bool result);

int main()
{
for(int i = 1; i < MAX_RANGE; i++)
{
init();
int ret = caculate(i);
result(i, ret);
}
return 0;
}

void init()
{
memset(next, 0, sizeof(next));
}

int caculate(int number)
{
int cnt = 0;
CBigNumber temp(number);
int ret;
while((ret = temp.isLychrelNumber()) == UNKNOWN)
{
if(cnt > TIME)
{
ret = YES;
break;
}
temp.add();
next[cnt++] = temp;
}
return ret;
}

void result(int number, int ret)
{
if(ret == YES)
{
setAllInNextTable(false);
cout<<number<<endl;
}
else
{
setAllInNextTable(true);
}
}

void setAllInNextTable(bool result)
{
for(int i = 0; next[i].size != 0; i++)
{
next[i].setValue(result);
}
}
2.BigNumber.h
#define MAX_TABLE_SIZE 1000000
#define MAX_DIGIT 18

bool value[MAX_TABLE_SIZE] = {0};
bool isCaculated[MAX_TABLE_SIZE] = {0};

bool isReverse(long long number)
{
int word[10] = {0};
int cnt = 0;
while(number)
{
word[cnt++] = number % 10;
number /= 10;
}
for(int i = 0; i < cnt; i++)
{
if( word[i] !=  word[cnt - i - 1])
{
return false;
}
}
return true;
}

bool isAllDigitSmallerThan5(long long number)
{
while(number)
{
int last = number % 10;
if(last >= 5)
return false;
number /= 10;
}
return true;
}

int isLychrelNumber(long long number)
{
if(isReverse(number) == true)
return 0;

if(isAllDigitSmallerThan5(number) == true)
return 0;

if(number >= MAX_TABLE_SIZE || isCaculated[number] == false)
return -1;

return !value[number];
}

#define MAX_SIZE 200
class CBigNumber
{
private:
long long data[MAX_SIZE];
bool isNumberTooBig();
bool isReverse();
bool isAllDigitSmallerThan5();
bool isInRecord();
public:
int size;
CBigNumber();
CBigNumber(const CBigNumber &B);
CBigNumber(long long normalData);
int isLychrelNumber();
void add();
void setValue(bool flag);
void print();
CBigNumber &operator=(const CBigNumber & B);
bool operator==(const CBigNumber & B);
CBigNumber getReverseNumber();
};
CBigNumber::CBigNumber()
{
size = 0;
memset(data, 0, sizeof(data));
}
CBigNumber::CBigNumber(const CBigNumber &B)
{
size = B.size;
for(int i = 0; i < B.size; i++)
data[i] = B.data[i];
}
CBigNumber::CBigNumber(long long normalData)
{
memset(data, 0, sizeof(data));
data[0] = normalData;
size = 1;
}
int CBigNumber::isLychrelNumber()
{
if(size == 1)
return ::isLychrelNumber(data[0]);

if(isNumberTooBig() == true)
return 1;

if(isReverse() == true)
return 0;

if(isAllDigitSmallerThan5() == true)
return 0;

if(isInRecord() == false)
return -1;

return !value[data[0]];
}
void CBigNumber::add()
{
CBigNumber reverse = getReverseNumber();
for(int i = 0; i < size; i++)
{
data[i] = data[i] + reverse.data[i];
if(data[i] > 1000000000000000000)
{
data[i] = data[i] - 1000000000000000000;
data[i+1]++;
}
}
if(data[size] > 0)
size++;
}
void CBigNumber::setValue(bool flag)
{
if(size == 1 && data[0] < MAX_TABLE_SIZE)
{
isCaculated[data[0]] = true;
value[data[0]] = flag;
}
}
void CBigNumber::print()
{
for(int i = 0; i < size; i++)
cout<<data[i];
}
CBigNumber& CBigNumber::operator=(const CBigNumber & B)
{
size = B.size;
for(int i = 0; i < size; i++)
data[i] = B.data[i];
return *this;
}
bool CBigNumber::operator==(const CBigNumber & B)
{
if(size != B.size)
return false;
for(int i = 0; i < size; i++)
if(data[i] != B.data[i])
return false;
return true;
}
bool CBigNumber::isNumberTooBig()
{
if(size >= MAX_SIZE)
return true;
return false;
}
bool CBigNumber::isReverse()
{
CBigNumber reverse = getReverseNumber();
if(reverse == *this)
return true;
else
return false;
}
bool CBigNumber::isAllDigitSmallerThan5()
{
for(int i = 0; i < size; i++)
if(::isAllDigitSmallerThan5(data[i]) =
7fe0
= false)
return false;
return true;
}
bool CBigNumber::isInRecord()
{
if(size > 1)
return false;
if(data[0] >= MAX_TABLE_SIZE)
return false;
return isCaculated[data[0]];
}
CBigNumber CBigNumber::getReverseNumber()
{
CBigNumber ret;

int digit[10000] = {0}, start;
for(int i = 0; i < size; i++)
{
start = i * 18;
long long temp = data[i];
while(temp)
{
digit[start++] = temp % 10;
temp = temp / 10;
}
}

memset(ret.data, 0, sizeof(ret.data));
for(int i = 0; i < start; i+=18)
{
for(int j = i; j < i+18; j++)
{
if(j >= start)break;
ret.data[ret.size] = ret.data[ret.size] * 10 + digit[j];
}
ret.size++;
}
return ret;
}


二、评论

1.main.cpp逻辑太复杂

2.不应该在.h中写实现代码

3.int CBigNumber::isLychrelNumber()函数太长,其中的判断不在一个逻辑层次

4.isNumberTooBig()优化效果不明显,却严重影响代码阅读,建议去掉

5.Record是对中间过程的缓存,建议更名为buffer

6.部分魔应定义为宏

7.垂直的函数顺序不好,应参考《代码简洁之道》5.2.3和5.2.5

8.部分命名需要重新设计
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: