実装

 前回の考え方にしたがってクラスを実装してみました。Add1Digitという名前にしてあります。

 キャリーオーバーを処理できるようにしてあります。コアになるのは、+の演算子オーバーロードしているところです。考え方は前回書いたとおりです。


Header

class Add1Digit {
public:
	// Constructor
	Add1Digit();
	Add1Digit(int num);

	// Accessor
	Abacus& getReg();
        bool getCarryOver() const;
	bool getCarryFrom() const;

	// Mutators
	void setReg(int num);
	void setCarryOver();
        void setCarryFrom(); // No needs to implement

	// Show the register status
	friend ostream& operator<<(ostream& out,Add1Digit& obj);

	// Operator overload
	Add1Digit& operator+(Abacus& obj);
	
private:
	Abacus reg_a; // 1-digit resiter 
        bool carryOver; // Carry over, borrow bit
	bool carryFrom; // Carry from lower digit

};

Implementation

// Constructor
Add1Digit::Add1Digit() :
	carryOver(false),carryFrom(false)
{
	reg_a.setNum(0);
}

Add1Digit::Add1Digit(int num) :
	carryOver(false),carryFrom(false)
{
	reg_a.setNum(num);
}

	// Accessor
Abacus& Add1Digit::getReg() {
	return this->reg_a;
}

bool Add1Digit::getCarryOver() const {
	return carryOver;
}


bool Add1Digit::getCarryFrom() const {
	return carryFrom;
}

// Mutators
void Add1Digit::setReg(int num) {
	reg_a.setNum(num);
}

void Add1Digit::setCarryOver() {
	carryOver = true;
}

void Add1Digit::setCarryFrom() {
	carryFrom = true; // No needs to implement
}

// Show the register status
ostream& operator<<(ostream& out,Add1Digit& obj) {
		out << obj.getReg() ;
		out << " CarryOver: " << obj.carryOver << endl;
		out << " CarryFrom: " << obj.carryFrom << endl;
		return out;
}

// Operator overload
Add1Digit& Add1Digit::operator+(Abacus& obj) {
	int a5,b5,c5; // flag 
	// a5 stands for the state of five-bean to be added
	// b5 stands for the state of five-bean to add
	// c5 stands for a1+b1 > 4 or not

	if (obj.getFive() == 1 )
		b5 = 1;
	else
		b5 = 0;

	if (reg_a.getFive() == 1)
		a5= 1;
	else
		a5 = 0;

	if ( reg_a.isOverFive(obj) )
		c5 = 1;
	else
		c5 = 0;

	cout << "a5 b5 c5: " << a5 <<b5<<c5 <<endl;

	if (c5 == 1) 
		reg_a.subCompOnes(obj);
	else
		reg_a.addOnes(obj);
		
	if ( a5+b5+c5 == 1 ) {
		if ( a5 == 0 ) {
			reg_a.setFive();
		}
    // * b5 or c5 == 0, do nothing)

	} else {
    // a5+b5+c5 == 2 or 3
    setCarryOver();
    if ( (b5 == 0) || (c5 == 0 )) {
      reg_a.clearFive();
    }
	} 

	return *this;

}

下の桁からの繰り上がり

現時点では、下の桁からの繰り上がりは反映してありません。(一応書いてはありますが。)

それは、そろばんの加算の計算の考え方が、1位の桁からではなく、一番上の桁から計算して、繰り上がりが出たら既に計算し終わった上位の桁に1を加えてまた戻るという操作を行うためです。

 したがって、4563+2442などは、千位の4+2=6、百位の5+4=9を計算し、十位の6+4=10でキャリーがでるので、百位に戻り、百位の9+1=10でまたキャリーが出るので、千位に戻り、6+1=7とし、結局700で十位までの計算が終わり、1位で3+3=5で、7005となるという操作をします。

このため、足し算においてはCarryFromを考えなくても、2桁以上の加算におけるアルゴリズムで、上の桁から計算し、途中でCarryOverが出たら、前の桁に戻って1を加える加算を再度行うことを再帰で行い、最後に1位に到達した時点で計算終了とすると考えればいいので、全加算器のように、被加算数 + (下の桁からの繰り上がり) + 加算数 と考えて計算しているわけではありません。
 
 筆算のように1位の桁から順に計算する場合はこうなるのですが、再帰計算をしています。
 このため、この実装は、加算器のクラスの方にではなく、2桁以上の計算をする際のアルゴリズムの方に反映することとします。