Completed
Push — master ( ccc8cf...e5263c )
by Derek Stephen
01:22
created

Fraction::getStringWhole()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 2
eloc 2
nc 2
nop 0
crap 2
1
<?php
2
3
namespace Del\Phi;
4
5
class Fraction
6
{
7
    /** @var int $whole */
8
    private $whole;
9
10
    /** @var int $numerator */
11
    private $numerator;
12
13
    /** @var int $denominator */
14
    private $denominator;
15
16
    /** @var bool $negative */
17
    private $negative;
18
19 5
    public function __construct($whole = 0, $numerator = 0, $denominator = 1)
20
    {
21 5
        $this->whole = $whole;
22 5
        $this->numerator = $numerator;
23 5
        $this->denominator = $denominator;
24 5
        $this->negative = false;
25 5
    }
26
27
    /**
28
     * @return int
29
     */
30 1
    public function getWhole()
31
    {
32 1
        return $this->whole;
33
    }
34
35
    /**
36
     * @param int $whole
37
     * @return Fraction
38
     */
39 4
    public function setWhole($whole)
40
    {
41 4
        $this->whole = $whole;
42 4
        return $this;
43
    }
44
45
    /**
46
     * @return int
47
     */
48 1
    public function getNumerator()
49
    {
50 1
        return $this->numerator;
51
    }
52
53
    /**
54
     * @param int $numerator
55
     * @return Fraction
56
     */
57 4
    public function setNumerator($numerator)
58
    {
59 4
        $this->numerator = $numerator;
60 4
        return $this;
61
    }
62
63
    /**
64
     * @return int
65
     */
66 1
    public function getDenominator()
67
    {
68 1
        return $this->denominator;
69
    }
70
71
    /**
72
     * @param int $denominator
73
     * @return Fraction
74
     */
75 4
    public function setDenominator($denominator)
76
    {
77 4
        $this->denominator = $denominator;
78 4
        return $this;
79
    }
80
81 1
    private function refactor()
82
    {
83
        // 9/8 would become 1 1/8 for instance
84 1
        if ($this->shouldRefactorWhole()) {
85 1
            $this->refactorWhole();
86
        }
87 1
        if ($this->shouldRefactorFraction()) {
88 1
            $this->refactorFraction();
89
        }
90 1
    }
91
92
    /**
93
     * @return bool
94
     */
95 1
    private function shouldRefactorWhole()
96
    {
97 1
        return $this->numerator >= $this->denominator
98 1
            && $this->denominator > 0;
99
    }
100
101
    /**
102
     * @return bool
103
     */
104 1
    private function shouldRefactorFraction()
105
    {
106 1
        return $this->numerator > 0
107 1
            && $this->denominator > 0;
108
    }
109
110 1
    private function refactorWhole()
111
    {
112
        // decrement $x and the numerator by the denominator each loop, and add to the whole
113 1
        for ($x = $this->numerator; $x >= $this->denominator; $x = $x - $this->denominator) {
114 1
            $this->whole ++;
115 1
            $this->numerator -= $this->denominator;
116
        }
117 1
    }
118
119 1
    private function refactorFraction()
120
    {
121 1
        $gcd = $this->getGreatestCommonDenominator($this->numerator, $this->denominator);
122 1
        $this->numerator = $this->numerator / $gcd;
123 1
        $this->denominator = $this->denominator / $gcd;
124 1
    }
125
126
    /**
127
     * @param int $x
128
     * @param int $y
129
     * @return int
130
     */
131 1
    private function getGreatestCommonDenominator($x, $y)
132
    {
133
        // first get the common denominators of both numerator and denominator
134 1
        $factorsX = $this->getFactors($x);
135 1
        $factorsY = $this->getFactors($y);
136
137
        // common denominators will be in both arrays, so get the intersect
138 1
        $commonDenominators = array_intersect($factorsX, $factorsY);
139
140
        // greatest common denominator is the highest number (last in the array)
141 1
        $gcd = array_pop($commonDenominators);
142
143 1
        return $gcd;
144
    }
145
146
    /**
147
     * @param int $num
148
     * @return array The common denominators of $num
149
     */
150 1
    private function getFactors($num)
151
    {
152 1
        $factors = [];
153
        // get factors of the numerator
154 1
        for ($x = 1; $x <= $num; $x ++) {
155 1
            if ($num % $x == 0) {
156 1
                $factors[] = $x;
157
            }
158
        }
159 1
        return $factors;
160
    }
161
162
    /**
163
     * @return bool
164
     */
165 1
    public function isNegative()
166
    {
167 1
        return $this->negative;
168
    }
169
170
    /**
171
     * @param bool $negative
172
     * @return Fraction
173
     */
174 1
    public function setNegative($negative)
175
    {
176 1
        $this->negative = $negative;
177 1
        return $this;
178
    }
179
180
    /**
181
     * @return bool
182
     */
183 1
    public function isInteger()
184
    {
185 1
        return $this->numerator % $this->denominator == 0;
186
    }
187
188
    /**
189
     * @return string
190
     */
191 1
    public function __toString()
192
    {
193 1
        $this->refactor();
194
195
        // if the whole is 0, don't display it
196 1
        $whole = $this->getStringWhole();
197 1
        $fraction = $this->getStringFraction();
198 1
        return $this->formatString($whole, $fraction);
199
    }
200
201
    /**
202
     * @return string
203
     */
204 1
    private function getStringWhole()
205
    {
206 1
        return $this->whole == 0 ? '' : (string) $this->whole;
207
    }
208
209
    /**
210
     * @return string
211
     */
212 1
    private function getStringFraction()
213
    {
214 1
        return $this->numerator > 0 && $this->denominator > 0 ? $this->numerator.'/'.$this->denominator : '';;
215
    }
216
217
    /**
218
     * @param string $whole
219
     * @param string $fraction
220
     * @return string
221
     */
222 1
    private function formatString($whole, $fraction)
223
    {
224 1
        $space = ($whole && $fraction) ? ' ' : '';
225 1
        return empty($whole.$space.$fraction) ? '0' : $whole.$space.$fraction;
226
    }
227
228
    /**
229
     * @return float
230
     */
231 1
    public function toDecimal()
232
    {
233
        /*
234
         * a divide symbol. so this is broken and will need refactoring to be accurate. ;-)
235
         */
236 1
        $decimal = $this->numerator / $this->denominator;
237 1
        $number =  $this->whole + $decimal;
238 1
        return $number;
239
    }
240
}