-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfraction.hpp
More file actions
118 lines (100 loc) · 4.28 KB
/
Copy pathfraction.hpp
File metadata and controls
118 lines (100 loc) · 4.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#ifndef FRACTION_HPP
#define FRACTION_HPP
#include <stdexcept>
#include <string>
#include "bigint.hpp"
struct Fraction {
BigInt numerator;
BigInt denominator;
Fraction() : numerator(0), denominator(1) {}
Fraction(const int &num) : numerator(num), denominator(1) {}
Fraction(const intmax_t num) : numerator(num), denominator(1) {}
Fraction(const uintmax_t num) : numerator(num), denominator(1) {}
Fraction(const BigInt &num) : numerator(num), denominator(1) {}
Fraction(const BigInt &num, const BigInt &den) : numerator(num), denominator(den) {
if (denominator.is_zero())
throw std::domain_error("Denominator cannot be zero.");
simplify();
}
explicit Fraction(const std::string &s) { from_str(s); }
Fraction &set(const BigInt &num) {
return this->numerator = num, this->denominator.set((uintmax_t)1), *this;
}
Fraction &set(const BigInt &num, const BigInt &den) {
this->numerator = num, this->denominator = den;
if (denominator.is_zero())
throw std::domain_error("Denominator cannot be zero.");
return simplify(), *this;
}
void simplify() {
BigInt gcd = find_gcd(numerator, denominator);
numerator /= gcd, denominator /= gcd;
if (denominator.is_negative())
numerator = -numerator, denominator = -denominator;
}
static BigInt find_gcd(BigInt a, BigInt b) {
BigInt *x = &a, *y = &b;
for (; !y->is_zero(); std::swap(x, y))
*x %= *y;
return *x;
}
Fraction operator+(const Fraction &other) const {
return Fraction(numerator * other.denominator + other.numerator * denominator,
denominator * other.denominator);
}
Fraction operator-(const Fraction &other) const {
return Fraction(numerator * other.denominator - other.numerator * denominator,
denominator * other.denominator);
}
Fraction operator*(const Fraction &other) const {
return Fraction(numerator * other.numerator, denominator * other.denominator);
}
Fraction operator/(const Fraction &other) const {
return Fraction(numerator * other.denominator, denominator * other.numerator);
}
bool operator==(const Fraction &other) const {
return numerator == other.numerator && denominator == other.denominator;
}
bool operator!=(const Fraction &other) const { return !(*this == other); }
bool operator<(const Fraction &other) const {
return numerator * other.denominator < other.numerator * denominator;
}
bool operator<=(const Fraction &other) const {
return numerator * other.denominator <= other.numerator * denominator;
}
bool operator>(const Fraction &other) const {
return numerator * other.denominator > other.numerator * denominator;
}
bool operator>=(const Fraction &other) const {
return numerator * other.denominator >= other.numerator * denominator;
}
Fraction &operator+=(const Fraction &other) { return *this = *this + other; }
Fraction &operator-=(const Fraction &other) { return *this = *this - other; }
Fraction &operator*=(const Fraction &other) { return *this = *this * other; }
Fraction &operator/=(const Fraction &other) { return *this = *this / other; }
Fraction operator+() const { return *this; }
Fraction operator-() const { return Fraction(-numerator, denominator); }
Fraction operator~() const { return Fraction(denominator, numerator); }
bool is_zero() const { return numerator.is_zero(); }
bool is_one() const { return numerator.is_one() && denominator.is_one(); }
bool is_minus_one() const { return numerator.is_minus_one() && denominator.is_one(); }
bool is_negative() const { return numerator.is_negative(); }
explicit operator bool() const { return !is_zero(); }
std::string to_string() const {
if (denominator.is_one())
return numerator.to_str();
return numerator.to_str() + "/" + denominator.to_str();
}
std::string to_str() const { return to_string(); }
Fraction &from_str(const std::string &input) {
size_t bar = input.find('/');
if (bar == std::string::npos)
return this->set(BigInt(input));
return this->set(BigInt(input.substr(0, bar)), BigInt(input.substr(bar + 1)));
}
};
Fraction operator""_frac(unsigned long long num) { return Fraction(BigInt((uintmax_t)num)); }
namespace std {
std::string to_string(const Fraction &f) { return f.to_string(); }
} // namespace std
#endif // FRACTION_HPP