1 /***************************************************************************
2 ratio.cpp - source code of class ratio
4 begin : Tue Nov 27 16:40:42 CET 2001
5 copyright : (C) 2001-2004 by Sebastian Stein
6 email : seb.kde@hpfsc.de
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
21 #include "primenumber.h"
23 /* ----- public member functions ----- */
26 ratio::ratio(int pnumerator
, int pdenominator
):m_numerator(pnumerator
), m_denominator(pdenominator
)
29 kdDebug() << "constructor ratio" << endl
;
32 // denominator is never allowed to be 0
36 // reduce the new ratio
40 /* copy constructor */
41 ratio::ratio(const ratio
& copy_ratio
)
44 kdDebug() << "copy constructor ratio" << endl
;
47 setNumerator(copy_ratio
.numerator(), false);
48 setDenominator(copy_ratio
.denominator(), false);
55 kdDebug() << "destructor ratio" << endl
;
59 /* displays the ratio on stdout; just for debugging */
60 QTextStream
& ratio::display(QTextStream
& str
) const
62 int tmp_width
= str
.width();
63 str
<< qSetW(5) << " ";
64 str
<< qSetW(5) << m_numerator
<< endl
;
65 str
<< qSetW(tmp_width
) << " ";
66 str
<< " ----- " << endl
;
67 str
<< qSetW(tmp_width
) << " ";
68 return str
<< qSetW(5) << m_denominator
;
71 /* return the numerator */
72 int ratio::numerator() const
77 /* return the denominator */
78 int ratio::denominator() const
83 /* set the numerator */
84 void ratio::setNumerator(int pnumerator
, bool reduce_it
)
86 m_numerator
= pnumerator
;
88 // check, if we have to reduce the ratio
89 if (reduce_it
== true)
95 /* set the denominator */
96 void ratio::setDenominator(int pdenominator
, bool reduce_it
)
98 /* denominator is not allowed to be 0 */
102 m_denominator
= pdenominator
;
104 // check, if we have to reduce the ratio
105 if (reduce_it
== true)
111 /* add a ratio to a ratio like c = a + b */
112 ratio
ratio::operator+(ratio addend
)
114 // this object will be returned as the sum
117 // calculate and set the numerator without reducing
118 sum
.setNumerator(m_numerator
* addend
.denominator()
119 + addend
.numerator() * m_denominator
, false);
121 // calculate and set the denominator without reducing
122 sum
.setDenominator(m_denominator
* addend
.denominator(), false);
130 /* sub a ratio from a ratio like c = a - b */
131 ratio
ratio::operator-(ratio subtrahend
)
133 /* this object will be returned as the difference */
136 /* change the sign of the subtrahend, so we can handle it as an addition */
137 subtrahend
.change_sign();
138 diff
= operator+(subtrahend
);
140 /* we have to change the sign back, so everything will be as before */
141 subtrahend
.change_sign();
143 /* return the difference */
147 /* mul a ratio with a ratio like c = a * b */
148 ratio
ratio::operator*(ratio factor
)
150 // this object will be returned as the product
153 // calculate and set numerator and denominator without reducing
154 product
.setNumerator(m_numerator
* factor
.numerator(), false);
155 product
.setDenominator(m_denominator
* factor
.denominator(), false);
157 // reduce the product
163 /* div a ratio with a ratio like c = a / b */
164 ratio
ratio::operator/(ratio divisor
)
166 /* this object will be returned as the quotient */
167 ratio
quotient(0, 1);
169 /* exchange numerator and denominator so we can handle as multiplication */
171 quotient
= operator*(divisor
);
173 /* go back to the original state */
179 /* we need this for initialization during a function prototyp;
180 * ratio fraction = 0 */
181 ratio
ratio::operator=(int dummy
)
189 /* check, if the ratios are equivalent; -1/2 == 1/-2 -> TRUE */
190 bool ratio::operator==(ratio right
)
192 signed short orig_sign
= 1, right_sign
= 1;
194 /* we do not check the presign at this point */
195 if (QABS(m_numerator
) != QABS(right
.numerator()))
197 if (QABS(m_denominator
) != QABS(right
.denominator()))
200 /* check if the signs of the ratios are equivalent */
203 if (m_denominator
< 0)
205 if (right
.numerator() < 0)
207 if (right
.denominator() < 0)
210 if (orig_sign
!= right_sign
)
216 bool ratio::operator<(ratio right
)
218 signed short sign
= 1;
219 ratio tmp_ratio
= ratio(m_numerator
, m_denominator
) - right
;
221 // check for this == right
222 if (tmp_ratio
== ratio(0, 1))
225 // get the presign of the diff
226 if (tmp_ratio
.numerator() < 0)
228 if (tmp_ratio
.denominator() < 0)
231 // if the diff is negative, this is smaller then right
240 bool ratio::operator>(ratio right
)
242 signed short sign
= 1;
243 ratio tmp_ratio
= ratio(m_numerator
, m_denominator
) - right
;
245 // check for this == right
246 if (tmp_ratio
== ratio(0, 1))
249 // get the presign of the diff
250 if (tmp_ratio
.numerator() < 0)
252 if (tmp_ratio
.denominator() < 0)
255 // if the diff is positive, this is smaller then right
264 /* ----- private member functions ----- */
266 /* reduce the ratio */
269 /* we try prime numbers as divisors; I think it is the fastet way to do */
271 short sign_numerator
= 0, sign_denominator
= 0;
273 /* make the whole ratio positive; save the signs; it is easier to reduce
274 * the ratio, if it is positive */
275 if (m_numerator
< 0) // save numerator sign
280 if (m_denominator
< 0) // save denominator sign
282 sign_denominator
= 1;
286 for (int divisor
= number
.get_first();
287 divisor
<= m_numerator
&& divisor
<= m_denominator
; divisor
= number
.get_next())
292 kdDebug() << "ratio::reduce() -> divisor == 0 !!!" << endl
;
293 kdDebug() << "m_numerator: " << m_numerator
<< endl
;
294 kdDebug() << "m_denominator: " << m_denominator
<< endl
;
297 /* so that the application does not crash with a floating
298 * point exception; the error should not appear, but in some
299 * cases it does and I do not know why */
303 /* is the prime number a divisor of numerator and denominator? */
304 if ((m_numerator
% divisor
== 0) && (m_denominator
% divisor
== 0))
306 /* reduce the ratio by the divisor */
307 m_numerator
/= divisor
;
308 m_denominator
/= divisor
;
310 /* we have to go recursive, if the 2 is a divisor, because there
311 * is no way to step one number before 2 -> there is no prime
312 * number smaller than 2 */
316 number
.move_back(); // the prime number could be a divisor again
317 } // if ((zaehler % divisor == 0) && (nenner % divisor == 0))
318 } // for (unsigned int divisor = number.get_first(); ...
320 /* restore the correct signs */
323 if (sign_denominator
)
325 if (m_numerator
== 0)
331 /* exchange numerator and denominator */
332 void ratio::reziproc()
334 int temp
= m_numerator
;
335 m_numerator
= m_denominator
;
336 m_denominator
= temp
;
342 /* ------ private member functions ------ */
344 /* change the sign of the ratio; ratio = ratio * -1 */
345 void ratio::change_sign()
347 /* this would be enough to change the sign of the ratio */
350 /* if numerator and denominator both are negative, make them positive;
351 * if denominator is negative and numerator positive, exchange the sign */
352 if ((m_numerator
< 0 && m_denominator
< 0) || (m_numerator
> 0 && m_denominator
< 0))
362 /* ------ some prototyps of non class functions ------ */
364 // it is possible to stram ratio_object
365 QTextStream
& operator<<(QTextStream
& str
, const ratio
& pratio
)
367 return pratio
.display(str
);