一、代码
1.main.cpp
#include <iostream> using namespace std; #include "BigNumber.h" #define MAX_RANGE 1000 #define LOOP_TIMES 10000 #ifdef __UT__ int ut_main() #else int main() #endif { for(int i = 195; i < MAX_RANGE; i++) { CBigNumber number(i); if(number.isLychrelNumber(LOOP_TIMES) == true) cout<<i<<endl; } return 0;2.BigNumber.h
#pragma once #include <string.h> #define MAX_SIZE 200 class CBigNumber { private: long long data[MAX_SIZE]; #ifdef __UT__ public: #endif bool isNumberTooBig(); bool isReverse(); bool isAllDigitSmallerThan5(); bool isInRecord(); void initLychrelAlgorithm(int loopTimes); bool caculateLychrel(int loopTimes); void recordInBuffer(bool result); int number2Digit(int *digit); void reverseDigit(int *digit, int len); CBigNumber digit2Number(int *digit, int len); int decideByLimit(); int decideByRule(); int decideByRecord(); public: int size; CBigNumber(); CBigNumber(const CBigNumber &B); CBigNumber(long long normalData); int preDecide(); void add(); void setValue(bool flag); void print(); CBigNumber &operator=(const CBigNumber & B); bool operator==(const CBigNumber & B); CBigNumber getReverseNumber(); bool isLychrelNumber(int loopTimes); }; bool isReverse(long long number);3.BigNumber.cpp
#include <iostream> #include "BigNumber.h" using namespace std; #define BUFFER_SIZE 1000000 #define MAX_DIGIT 18 #define NO 0 #define YES 1 #define CAN_NOT_DECIDE 2 CBigNumber *next; bool isNotLyrched[BUFFER_SIZE] = {0}; bool isCaculated[BUFFER_SIZE] = {0}; bool isAllDigitSmallerThan5(long long number) { while(number) { int last = number % 10; if(last >= 5) return false; number /= 10; } return true; } CBigNumber::CBigNumber() { size = 0; memset(data, 0, sizeof(data)); } CBigNumber::CBigNumber(const CBigNumber &B) { size = B.size; memset(data, 0, sizeof(data)); 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::preDecide() { int ret = CAN_NOT_DECIDE; ret = decideByLimit(); if(ret != CAN_NOT_DECIDE) return ret; ret = decideByRule(); if(ret != CAN_NOT_DECIDE) return ret; ret = decideByRecord(); if(ret != CAN_NOT_DECIDE) return ret; return ret; } int CBigNumber::decideByLimit() { if(isNumberTooBig() == true) return YES; if(isAllDigitSmallerThan5() == true) return NO; return CAN_NOT_DECIDE; } int CBigNumber::decideByRule() { if(isReverse()) return NO; return CAN_NOT_DECIDE; } int CBigNumber::decideByRecord() { if(isInRecord() == false) return CAN_NOT_DECIDE; return !isNotLyrched[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] < BUFFER_SIZE) { isCaculated[data[0]] = true; isNotLyrched[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; memset(data, 0, sizeof(data)); 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] >= BUFFER_SIZE) return false; return isCaculated[data[0]]; } CBigNumber CBigNumber::getReverseNumber() { CBigNumber ret; int digit[10000] = {0}; int len = number2Digit(digit); reverseDigit(digit, len); ret = digit2Number(digit, len); return ret; } int CBigNumber::number2Digit(int *digit) { int start = 0; for(int i = 0; i < size; i++) { start = i * MAX_DIGIT; long long temp = data[i]; while(temp) { digit[start++] = temp % 10; temp = temp / 10; } } return start; } void CBigNumber::reverseDigit(int *digit, int len) { int midIndex = (len - 1) / 2; for(int i = 0; i <= midIndex; i++) swap(digit[i], digit[len - 1 - i]); } CBigNumber CBigNumber::digit2Number(int *digit, int len) { CBigNumber ret; memset(ret.data, 0, sizeof(ret.data)); for(int i = 0; i < len; i+=MAX_DIGIT) { for(int j = i + MAX_DIGIT-1; j >= i; j--) { if(j >= len)continue; ret.data[ret.size] = ret.data[ret.size] * 10 + digit[j]; } ret.size++; } return ret; } bool CBigNumber::isLychrelNumber(int loopTimes) { bool ret = false; initLychrelAlgorithm(loopTimes); ret = caculateLychrel(loopTimes); recordInBuffer(ret); delete []next; return ret; } void CBigNumber::initLychrelAlgorithm(int loopTimes) { next = new CBigNumber[loopTimes]; memset(next, 0, sizeof(next)); } bool CBigNumber::caculateLychrel(int loopTimes) { int cnt = 0, ret; CBigNumber temp = *this; while((ret = temp.preDecide()) == CAN_NOT_DECIDE) { if(cnt > loopTimes) return true; temp.add(); next[cnt++] = temp; } return ret; } void CBigNumber::recordInBuffer(bool result) { for(int i = 0; next[i].size != 0; i++) { next[i].setValue(!result); } }
二、评论
1. MAX_SIZE最好换个名字,忘记建议换成什么了
2. 函数名isInRecord ---> inInBuffer (遗留问题)
3. CBigNumber对外提供的功能函数只有bool isLychrelNumber(int loopTimes);,其它的大部分可以移至private
4. 垂直顺序仍然存在问题 (遗留问题)
5. 函数isLychrelNumber中的“Delete []next;” in 应该封装成一个函数,与上面的初始化函数相对应
6. 变量名next让人难以理解
7. 增加用于跟踪错误的代码
8. 当输入参数loopTime=0时,函数会出错
9. 宏NO、YES、CAN_NOT_DECIDE是一组的,可以用typedef
10. 增加成员函数operator+
11. 函数名add ---> caculate
12. 函数名number2digit ---> data2digit
13. 将BigNumber的处理与Lychrel的逻辑混到一起了,应该分出一个CLychrel类
14.用于优化的 buffer最好也分出一个类
15.回文数的英文是palindrome
16.C风格与C++风格混用
17.CBigNumber.h中L42是多余的