#include "Rational.h" #include "Fraction/Fraction.h" #include #include #include #include using namespace std; Rational::Rational(){ num = 0; denum = 1; } Rational::Rational(int num1){ num = num1; denum = 1; } Rational::Rational(int num1, int num2) { num = num1; denum = num2; simple(); } Rational::Rational(float x) { const uint32_t bits = *(uint32_t*)(&x); const uint32_t signBit = bits >> 31; const uint32_t exponentBits = (bits >> 23) & 0xff; const uint32_t mantisBits = bits & 0x7fffff; uint32_t significand = (1u << 23u) | mantisBits; const int64_t sign = signBit ? -1 : 1; const int32_t exp = exponentBits - 127 - 23; static uint32_t smth = 1 << (uint32_t)(-exp); num = sign * (int64_t)(significand); denum = smth; simple(); } Rational::Rational(double x) { const unsigned long long int bits = *(unsigned long long int*)(&x); const unsigned long long int signBit = (bits >> 63) & 1; const unsigned long long int exponentBits = (bits >> 52) & 0x7ff; const unsigned long long int mantisBits = bits & 0xFFFFFFFFFFFFF; unsigned long long int significant = (long long int)pow(2, 52) | mantisBits; if (exponentBits == 0 and mantisBits == 0) { num = 0; denum = 1; } else if(exponentBits == 2046) { throw "Rational doesn't support NaN or Inf"; } const long long int sign = signBit ? -1 : 1; const long long int exp = exponentBits - 1023 - 52; num = (long long int)(sign * significant); denum = (long long int)pow(2, -exp); simple(); } Rational& Rational::operator += (const Rational& r) { Rational newrr = r; while (INT64_MAX - num < r.num or INT64_MAX - denum < r.denum) { if(num > 10000 or denum > 10000) { Fraction f(*this); f.layers.pop(); Rational newr(f); num = newr.num; denum = newr.denum; } if(r.num > 10000 or r.denum > 10000) { Fraction f(r); f.layers.pop(); newrr = Rational(f); } } int scm = lcm(denum, newrr.denum); num = (num * (scm/denum) + newrr.num * (scm/newrr.denum)); denum = scm; return *this; } Rational Rational :: operator + (const Rational& r) const { Rational res(*this); return res += r; } Rational& Rational::operator -= (const Rational& r) { int scm = lcm(denum, r.denum); num = (num * (scm/denum) - r.num * (scm/r.denum)); denum = scm; return *this; } Rational Rational :: operator - (const Rational& r) const { Rational res(*this); return res -= r; } Rational& Rational::operator *= (const Rational& r) { Rational newrr = r; while (INT64_MAX / num < r.num or INT64_MAX / denum < r.denum) { if(num > 10000 or denum > 10000) { Fraction f(*this); f.layers.pop(); Rational newr(f); num = newr.num; denum = newr.denum; } if(r.num > 10000 or r.denum > 10000) { Fraction f(r); f.layers.pop(); newrr = Rational(f); } } num *= newrr.num; denum *= newrr.denum; simple(); return *this; } Rational Rational :: operator * (const Rational& r) const { Rational res(*this); return res *= r; } Rational& Rational::operator /= (const Rational& r) { num *= r.denum; denum *= r.num; simple(); return *this; } Rational Rational :: operator / (const Rational& r) const { Rational res(*this); return res /= r; } Rational Rational :: operator -() const { return Rational(-num, denum); } ostream& operator <<(ostream& out, const Rational& r) { return out << '(' << r.num << ")/(" << r.denum << ')'; } Rational::operator double() const { return ((double)num/(double)denum); } Rational::operator int() const { return int(double(*this)); } long long int Rational::lcm(long long int num1, long long int num2) { int result = 1; for(int dnum = 2; num1 > 1 or num2 > 1; dnum++) { if(num1%dnum==0 or num2%dnum==0) { num1%dnum==0 ? num1/=dnum : num1*1; num2%dnum==0 ? num2/=dnum : num1*1; result *= dnum; dnum--; } } return result; } long long int Rational::gcd(long long int num1, long long int num2) { while (num1 && num2) if (num1 >= num2) num1 %= num2; else num2 %= num1; return num1 | num2; } void Rational::simple() { long long int gct = gcd(num, denum); num /= gct; denum /= gct; } Rational Rational::sqrt() { cout << "Real sqrt" << endl; Rational a = *this; Rational x = *this; for (long long int i = 0; i < 10000; i++) { x = (x + (a / x)) / (Rational)2; } return x; }