Rational.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include "Rational.h"
  2. #include <iostream>
  3. #include <iomanip>
  4. #include <bitset>
  5. #include <math.h>
  6. using namespace std;
  7. Rational::Rational(){
  8. num = 0;
  9. denum = 1;
  10. }
  11. Rational::Rational(int num1, int num2)
  12. {
  13. num = num1;
  14. denum = num2;
  15. simple();
  16. }
  17. Rational::Rational(float x)
  18. {
  19. const uint32_t bits = *(uint32_t*)(&x);
  20. const uint32_t signBit = bits >> 31;
  21. const uint32_t exponentBits = (bits >> 23) & 0xff;
  22. const uint32_t mantisBits = bits & 0x7fffff;
  23. uint32_t significand = (1u << 23u) | mantisBits;
  24. const int64_t sign = signBit ? -1 : 1;
  25. const int32_t exp = exponentBits - 127 - 23;
  26. static uint32_t smth = 1 << (uint32_t)(-exp);
  27. num = sign * (int64_t)(significand);
  28. denum = smth;
  29. simple();
  30. }
  31. Rational::Rational(double x)
  32. {
  33. const unsigned long long int bits = *(unsigned long long int*)(&x);
  34. const unsigned long long int signBit = (bits >> 63) & 1;
  35. const unsigned long long int exponentBits = (bits >> 52) & 0x7ff;
  36. const unsigned long long int mantisBits = bits & 0xFFFFFFFFFFFFF;
  37. unsigned long long int significant = (long long int)pow(2, 52) | mantisBits;
  38. if (exponentBits == 0 and mantisBits == 0)
  39. {
  40. num = 0;
  41. denum = 1;
  42. }
  43. else if(exponentBits == 2046)
  44. {
  45. throw "Rational doesn't support NaN or Inf";
  46. }
  47. const long long int sign = signBit ? -1 : 1;
  48. const long long int exp = exponentBits - 1023 - 52;
  49. num = (long long int)(sign * significant);
  50. denum = (long long int)pow(2, -exp);
  51. simple();
  52. }
  53. Rational& Rational::operator += (const Rational& r)
  54. {
  55. int scm = lcm(denum, r.denum);
  56. num = (num * (scm/denum) + r.num * (scm/r.denum));
  57. denum = scm;
  58. return *this;
  59. }
  60. Rational Rational :: operator + (const Rational& r) const
  61. {
  62. Rational res(*this);
  63. return res += r;
  64. }
  65. Rational& Rational::operator -= (const Rational& r)
  66. {
  67. int scm = lcm(denum, r.denum);
  68. num = (num * (scm/denum) - r.num * (scm/r.denum));
  69. denum = scm;
  70. return *this;
  71. }
  72. Rational Rational :: operator - (const Rational& r) const
  73. {
  74. Rational res(*this);
  75. return res -= r;
  76. }
  77. Rational& Rational::operator *= (const Rational& r)
  78. {
  79. num *= r.num;
  80. denum *= r.denum;
  81. simple();
  82. return *this;
  83. }
  84. Rational Rational :: operator * (const Rational& r) const
  85. {
  86. Rational res(*this);
  87. return res *= r;
  88. }
  89. Rational& Rational::operator /= (const Rational& r)
  90. {
  91. num *= r.denum;
  92. denum *= r.num;
  93. simple();
  94. return *this;
  95. }
  96. Rational Rational :: operator / (const Rational& r) const
  97. {
  98. Rational res(*this);
  99. return res /= r;
  100. }
  101. ostream& operator <<(ostream& out, const Rational& r)
  102. {
  103. return out << '(' << r.num << ")/(" << r.denum << ')';
  104. }
  105. Rational::operator double() const
  106. {
  107. return ((double)num/(double)denum);
  108. }
  109. Rational::operator int() const
  110. {
  111. return int(double(*this));
  112. }
  113. long long int Rational::lcm(long long int num1, long long int num2)
  114. {
  115. int result = 1;
  116. for(int dnum = 2; num1 > 1 or num2 > 1; dnum++)
  117. {
  118. if(num1%dnum==0 or num2%dnum==0)
  119. {
  120. num1%dnum==0 ? num1/=dnum : num1*1;
  121. num2%dnum==0 ? num2/=dnum : num1*1;
  122. result *= dnum;
  123. dnum--;
  124. }
  125. }
  126. return result;
  127. }
  128. long long int Rational::gcd(long long int num1, long long int num2)
  129. {
  130. while (num1 && num2)
  131. if (num1 >= num2)
  132. num1 %= num2;
  133. else
  134. num2 %= num1;
  135. return num1 | num2;
  136. }
  137. void Rational::simple()
  138. {
  139. long long int gct = gcd(num, denum);
  140. num /= gct;
  141. denum /= gct;
  142. }