一、代码
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]) == 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.部分命名需要重新设计