■
実装
前回の考え方にしたがってクラスを実装してみました。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桁以上の計算をする際のアルゴリズムの方に反映することとします。