-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRational.cs
142 lines (116 loc) · 4.67 KB
/
Rational.cs
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using System;
namespace Incapsulation.RationalNumbers
{
public struct Rational
{
private readonly int _numerator;
private readonly int _denominator;
public Rational(int numerator, int denominator = 1)
{
IsNan = denominator == 0;
_numerator = numerator;
_denominator = numerator == 0 ? 1 : denominator;
}
public bool IsNan { get; }
private int Divisor
{
get
{
if (_numerator == 0 || _numerator == 1 || _denominator == 1)
return 1;
return _numerator < 0 && _denominator > 0 ? GetMaxCommonDivisor(_numerator, _denominator) :
_numerator > 0 && _denominator < 0 ? -GetMaxCommonDivisor(_numerator, _denominator) :
_numerator < 0 && _denominator < 0 ? -GetMaxCommonDivisor(_numerator, _denominator) :
_numerator > 0 && _denominator > 0 ? GetMaxCommonDivisor(_numerator, _denominator) :
-GetMaxCommonDivisor(_numerator, _denominator);
}
}
private static int GetMaxCommonDivisor(int num, int den)
{
num = Math.Abs(num);
den = Math.Abs(den);
while (num != den)
{
if (num > den)
num -= den;
else
den -= num;
}
return num;
}
public int Numerator
{
get => Divisor == 1 ? _numerator : _numerator / Divisor;
private set => Numerator = _numerator;
}
public int Denominator
{
get => Divisor == 1 ? _denominator : _denominator / Divisor;
private set => Denominator = _denominator;
}
public static Rational operator +(Rational a, Rational b)
{
if (a.IsNan || b.IsNan) return new Rational(1, 0);
if (a.Denominator == b.Denominator)
return new Rational(a.Numerator + b.Numerator, a.Denominator);
(int a, int b) multipliers;
if (a.Denominator < b.Denominator)
{
if (b.Denominator % a.Denominator == 0)
return new Rational(a._numerator * (b.Denominator / a.Denominator) + b._numerator, b._denominator);
multipliers = GetMultipliers(a.Denominator, b.Denominator);
a *= multipliers.a;
b *= multipliers.b;
return new Rational(a._numerator + b._numerator, a._denominator);
}
if (a.Denominator % b.Denominator == 0)
return new Rational(a._numerator + b._numerator * (a.Denominator / b.Denominator), a._denominator);
multipliers = GetMultipliers(b.Denominator, a.Denominator);
a *= multipliers.b;
b *= multipliers.a;
return new Rational(a._numerator + b._numerator, a._denominator);
}
public static Rational operator -(Rational a, Rational b)
{
return a + new Rational(-b.Numerator, b.Denominator);
}
public static Rational operator *(Rational rational, int x)
{
return new Rational(rational.Numerator * x, rational.Denominator * x);
}
public static Rational operator *(int x, Rational rational)
{
return rational * x;
}
public static Rational operator *(Rational a, Rational b)
{
if (a.IsNan || b.IsNan) return new Rational(1, 0);
return new Rational(a.Numerator * b.Numerator, a.Denominator * b.Denominator);
}
public static Rational operator /(Rational a, Rational b)
{
if (a.IsNan || b.IsNan || b.Denominator == 0) return new Rational(1, 0);
return new Rational(a.Numerator * b.Denominator, a.Denominator * b.Numerator);
}
public static implicit operator double(Rational rational)
{
if (rational.IsNan || rational.Denominator == 0)
return double.NaN;
return (double) rational.Numerator / rational.Denominator;
}
public static implicit operator Rational(int x)
{
return x == 0 ? new Rational(0, 1) : new Rational(x, 1);
}
public static explicit operator int(Rational rational)
{
if (rational.IsNan || rational.Numerator % rational.Denominator != 0)
throw new ArgumentException();
return rational.Numerator / rational.Denominator;
}
private static (int, int) GetMultipliers(int x, int y)
{
return y % x == 0 ? (y / x, y) : (y, x);
}
}
}