123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- #include "Rational.h"
- #include "Fraction/Fraction.h"
- #include <iostream>
- #include <iomanip>
- #include <bitset>
- #include <math.h>
- 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;
- }
|