LychrelNumber实现V2.0

来源:互联网 发布:商汤科技 算法开发 编辑:程序博客网 时间:2024/04/28 08:19

一、代码

1.main.cpp

#include <iostream>using namespace std;#include "BigNumber.h"#define MAX_RANGE 1000#define LOOP_TIMES 10000#ifdef __UT__int ut_main()#elseint 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 200class CBigNumber{private:long long data[MAX_SIZE];#ifdef __UT__public:#endifbool 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 2CBigNumber *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;elsereturn 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是多余的


0 0
原创粉丝点击