SchemeUnit* Rational::isEql(Number* number2) { if (!number2->exact_) { return new Boolean(false); } else if (number2->type_ == 1) { Rational* tmp2 = SCAST_RATIONAL(number2); Rational* tmp_dif = SCAST_RATIONAL(sub(tmp2)); if (tmp_dif->num_ == ZERO_) return new Boolean(true); else return new Boolean(false); } else if (number2->type_ == 3) { Complex* tmp2 = SCAST_COMPLEX(number2); Rational* tmp2_real = SCAST_RATIONAL(tmp2->real_); Rational* tmp2_imag = SCAST_RATIONAL(tmp2->imag_); if (tmp2_imag->num_!=ZERO_) return new Boolean(false); else { Rational* tmp_dif = SCAST_RATIONAL(sub(tmp2_real)); if (tmp_dif->num_ == ZERO_) return new Boolean(true); else return new Boolean(false); } } }
Number* Rational::mini(Number *number2) { if (this == number2) {return new Rational(*this); } Rational* tmp2 = SCAST_RATIONAL(number2); Rational* dis = SCAST_RATIONAL(sub(tmp2)); if (dis->num_.sgn_) return new Rational(*this); else return new Rational(*tmp2); }
Number* Rational::rem(Number* number2) { assert ( number2->type_==1 && "remainder is only for integer" ); Rational* tmp2 = SCAST_RATIONAL(number2); assert ( den_==ONE_ && tmp2->den_==ONE_ && "remainder is only for integer" ); return new Rational(num_%tmp2->num_, ONE_); }
Number* Rational::modulo(Number* obj){ Rational* tmpr = SCAST_RATIONAL(obj->toExact()); assert(denominator_==ONE and tmpr->denominator_==ONE and "madulo operation is only for Integer Type !"); if(numerator_.n.back() * tmpr->numerator_.n.back() >= 0) //除数和被除数同号 return new Rational(numerator_ % tmpr->numerator_ , ONE); else return new Rational(numerator_ % tmpr->numerator_+ tmpr->numerator_ , ONE); }
Number* Rational::lcm(Number* obj){ Rational* tmpr = SCAST_RATIONAL(obj->toExact()); assert(denominator_==ONE and tmpr->denominator_==ONE and "lcm operation is only for Integer Type !"); if(this->numerator_ == ZERO and tmpr->numerator_==ZERO) return new Rational(ZERO,ONE); return this->mul(tmpr)->div(this->gcd(tmpr))->abs(); }
Number* Rational::quo(Number* number2) { //assert ( number2->type_==1 && "quotient is only for integer" ); Rational* tmp2 = SCAST_RATIONAL(number2); assert ( den_==ONE_ && tmp2->den_==ONE_ && "quotient is only for integers" ); return new Rational(num_ / tmp2->num_, ONE_); }
Number *Rational::sub(Number *number2) { Rational *tmp = SCAST_RATIONAL(number2); Rational *result = new Rational(); result->num_ = num_*tmp->den_ - den_*tmp->num_; result->den_ = den_ * tmp->den_; result->reduce(); return result; }
Number* Rational::makeRec(Number* number2) { Rational* tmp2 = SCAST_RATIONAL(number2); Complex* c = new Complex; c->exact_ = true; c->real_ = new Rational(num_,den_); c->imag_ = new Rational(tmp2->num_,tmp2->den_); return c; }
Number* Rational::mod(Number* number2) { assert ( number2->type_==1 && "modulo is only for integer" ); Rational* tmp2 = SCAST_RATIONAL(number2); assert ( den_==ONE_ && tmp2->den_==ONE_ && "modulo is only for integer" ); BigInt remi = num_ % tmp2->num_; if (remi.sgn_ == tmp2->num_.sgn_) return new Rational(remi,ONE_); else { remi = remi + tmp2->num_; return new Rational(remi,ONE_); } }
//分数减法 Number *Rational::sub(Number *number2) { Rational *tmp = SCAST_RATIONAL(number2); Rational *result = new Rational(); result->numerator_ = numerator_*tmp->denominator_ - denominator_*tmp->numerator_; result->denominator_ = denominator_ * tmp->denominator_; result->reduce();//最后要进行约分 return result; }
Number* Rational::lcm(Number* number2) { assert ( number2->type_==1 && "lcm is only for integer" ); Rational* tmp2 = SCAST_RATIONAL(number2); if (num_ == ZERO_ || tmp2->num_ == ZERO_) return new Rational(ZERO_,ONE_); //assert ( den_==ONE_ && tmp2->den_==ONE_ && "lcm is only for integer" ); if (this == number2) {return new Rational(num_.abs(),den_); } BigInt lcm_num = BigInt::lcm(num_,tmp2->num_); BigInt gcd_num = BigInt::gcd(den_,tmp2->den_); Rational* res = new Rational(lcm_num,gcd_num); return res; }
Number *Rational::div(Number *number2) { Rational *tmp = SCAST_RATIONAL(number2); assert( tmp->num_!=ZERO_ && "divided by zero"); Rational *result = new Rational(); result->num_ = num_ * tmp->den_; //cout<<result->num_<<endl; result->den_ = den_ * tmp->num_; //cout<<result->den_<<endl; result->reduce(); return result; }
Number* Rational::expt(Number* obj){ if(sgn()<0){ Complex* c = new Complex(); c = SCAST_COMPLEX(c->convert(this)); Complex* d = SCAST_COMPLEX(c->convert(obj)); return c->expt(d); }else{ Float* tmpf = new Float(); tmpf = SCAST_FLOAT(tmpf->convert(obj)); return new Float(pow(double(*this), double(*SCAST_RATIONAL(obj)))); } }
Number *Rational::convert(Number *number2) { assert(number2->type_ <= type_); Rational *result=new Rational(); switch(number2->type_) { case RATIONAL: { Rational *tmp = SCAST_RATIONAL(number2); result->numerator_ = tmp->numerator_; result->denominator_ = tmp->denominator_; break; } default: assert(0 && "type_ not defined"); } result->reduce(); return result; }
Number* Rational::gcd(Number* obj){ Rational* tmpr = SCAST_RATIONAL(obj->toExact()); assert(denominator_==ONE and tmpr->denominator_==ONE and "gcd operation is only for Integer Type !"); LongInt num_abs = numerator_.getABS(), den_abs = tmpr->numerator_.getABS(); LongInt BIG = max(num_abs,den_abs); LongInt SMALL = min(num_abs,den_abs); if(SMALL==ZERO) return new Rational(BIG,ONE); LongInt tmp = BIG % SMALL; while(tmp!=ZERO) // 辗转相除法 欧几里得 { BIG = SMALL; SMALL = tmp; tmp = BIG % SMALL; } return new Rational(SMALL,ONE); }
Number* Rational::expp(Number* number2) { Rational* rtmp2 = SCAST_RATIONAL(number2); if (num_==ZERO_ && rtmp2->num_==ZERO_) return new Float(1); else if (num_==ZERO_ && rtmp2->num_!=ZERO_) return new Float(0); if(num_.sgn_) { Complex* c = new Complex; c = SCAST_COMPLEX(c->convert(this)); Complex* d = SCAST_COMPLEX(c->convert(rtmp2)); return c->expp(d); } else { Float* tmpf = new Float; tmpf = SCAST_FLOAT(tmpf->convert(rtmp2)); return new Float(pow(SCAST_FLOAT(tmpf->convert(this))->number_, tmpf->number_)); } }
SchemeUnit* Rational::nonInc(Number* number2) { Rational* dif = SCAST_RATIONAL(sub(number2)); return new Boolean(!dif->num_.sgn_); }
Boolean* Rational::JudgeLessThan(Number* obj){ Rational* toCheck = SCAST_RATIONAL(this->sub(obj->toExact())); return new Boolean(toCheck->sgn() < 0 ); }
Number* Rational::getMin(Number* obj){ Rational* toCheck = SCAST_RATIONAL(this->sub(obj->toExact())); return new Rational(toCheck->sgn()<0 ? (*this) :(*(SCAST_RATIONAL(obj)))); }
SchemeUnit* Rational::eql(Number* number2) { Rational* dif = SCAST_RATIONAL(sub(number2)); return new Boolean(dif->num_==ZERO_); }
Number* Rational::remainder(Number* obj){ Rational* tmpr = SCAST_RATIONAL(obj->toExact()); assert(denominator_==ONE and tmpr->denominator_==ONE and "remainder operation is only for Integer Type !"); return new Rational(numerator_ % tmpr->numerator_ , ONE); }
SchemeUnit* Rational::nonDec(Number* number2) { Rational* dif = SCAST_RATIONAL(sub(number2)); return new Boolean((dif->num_.sgn_) || (!dif->num_.sgn_ && dif->num_==ZERO_)); }
SchemeUnit* Rational::moDec(Number* number2) { Rational* dif = SCAST_RATIONAL(sub(number2)); return new Boolean(!dif->num_.sgn_ && dif->num_!=ZERO_); }