LychrelNumber实现V2.0

一、代码

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是多余的


你可能感兴趣的:(code,重构,clean,lychrel)