rational.h

Ir a la documentación de este archivo.
00001 // rational.h   (c) 2005 [email protected]
00002 
00003 /** \file  rational.h
00004     \brief Declara el tipo \c "rational".
00005     - La clase \c rational implementa las operaciones aritméticas
00006       principales para números rationales.
00007 
00008     - <code> [1/3] == [2/6] ==  ...   [9/27] == ... </code>
00009     - <code> [1/3]  * [2/6] / [3/9] - [9/27] </code>
00010 
00011     - Permite usar racionales en cualquier sitio en donde se puedan
00012       usar valores numéricos.
00013 
00014     \author Adolfo Di Mare <[email protected]>
00015     \date   2005
00016 */
00017 
00018 
00019 #ifndef rational_h
00020 #define rational_h ///< Evita la inclusión múltiple
00021 
00022 #define  INCLUDE_iostream
00023 #include "ADH_port.h"
00024 
00025 OPEN_namespace(ADH)
00026 USING_namespace(ADH);
00027 
00028 /**  La clase \c rational implementa las operaciones aritméticas
00029      principales para números rationales.
00030      - <code> [1/3] == [2/6] ==  ...   [9/27] == ... </code>
00031      - <code> [1/3]  * [2/6] / [3/9] - [9/27] </code>
00032 */
00033 class rational {
00034 private:
00035     long m_num; ///< Numerador
00036     long m_den; ///< Denominador
00037 
00038     void Simplify();
00039 
00040 public:
00041     // constructores
00042     rational() : m_num(0), m_den(1) { }  ///< Constructor de vector
00043     rational(long num) : m_num(num), m_den(1) { } ///< Constructor a partir de un valor entero
00044     rational(long num, long den)
00045         : m_num(num), m_den(den) { Simplify(); } ///< Constructor a partir de un valor quedbrado
00046     rational(const rational& o)       /// Constructor de copia
00047         { m_num = o.m_num, m_den = o.m_den; }
00048     ~rational() { }      ///< Destructor
00049 
00050     void set(long num=0, long den=1);  // Le cambia el valor a \c "*this"
00051 
00052     long num() const { return m_num; }  ///< Copia del numerador
00053     long den() const { return m_den; }  ///< Copia del denominador
00054 
00055 //  void num(long n) { m_num=n; Simplify(); }  // FEO
00056 //  void den(long d) { m_den= ( d!=0 ? d : m_den) ; Simplify(); }  // FEO
00057 
00058     rational& operator  = (const rational&);  // Asignación (copia)
00059     rational& operator  = (long);
00060     rational& Swap ( rational& );
00061 
00062     rational& operator += (const rational&);
00063     rational& operator -= (const rational&);
00064     rational& operator *= (const rational&);
00065     rational& operator /= (const rational&);
00066 
00067     rational operator  - () const;              // menos unario
00068 
00069     friend rational operator + (const rational&, const rational&);
00070     friend rational operator - (const rational&, const rational&);
00071     friend rational operator * (const rational&, const rational&);
00072     friend rational operator / (const rational&, const rational&);
00073 
00074     friend bool operator == (const rational&, const rational&);
00075     friend bool operator <  (const rational&, const rational&);
00076     friend bool operator != (const rational&, const rational&);
00077     friend bool operator <= (const rational&, const rational&);
00078     friend bool operator >= (const rational&, const rational&);
00079     friend bool operator >  (const rational&, const rational&);
00080 
00081     friend ostream& operator << (ostream &, const rational& );
00082     friend istream& operator >> (istream &,       rational& );
00083     rational& fromString (const char* num);
00084 
00085     friend double real   (const rational& );   // Conversión a real
00086     friend long   integer(const rational& );   // Conversión a long
00087 
00088     friend bool check_ok( const rational& r ); // Ok()
00089 //  excluidos porque producen ambigüedad con operadores aritméticos
00090 //  operator double () { return double(m_num) / double(m_den); }
00091 //  operator long   () { return        m_num  /        m_den ; }
00092 }; // rational
00093 
00094 long mcd(long x, long y); // Calcula el Máximo Común Divisor
00095 
00096 /// Sinónimo de \c mcd(x,y) <code> [ inline ] </code>
00097 inline long gcd(long x, long y) { return mcd(x,y); }
00098 
00099 /// Cambia el valor del número rational a \c "n/d"
00100 inline void rational::set(long n, long d) {
00101     m_num = n;
00102     m_den = d;
00103     Simplify();
00104 }
00105 
00106 /** Copia desde \c "o".
00107     - El valor anterior de \c "*this" se pierde.
00108     \par Complejidad:
00109          O( \c 1 )
00110     \returns *this
00111     \see http://www.di-mare.com/adolfo/binder/c04.htm#sc05
00112 */
00113 inline rational& rational::operator = (const rational& o) {
00114     m_num = o.m_num,
00115     m_den = o.m_den;
00116 
00117 //  sobra invocar a "Simplify()" pues "o" ya está simplificado
00118     return *this;
00119 }  // operator =
00120 
00121 /** Intercambia los valores de \c "*this" y \c "o"
00122 
00123       \par Complejidad:
00124          O( \c 1 )
00125 
00126     \returns *this
00127 
00128     \see http://www.di-mare.com/adolfo/binder/c04.htm#sc08
00129 */
00130 inline rational& rational::Swap ( rational& o ) {
00131     #if 1
00132         rational tmp = o;
00133         o = *this;
00134         *this = tmp;
00135     #else
00136         // Esto NO funciona para objetos, métodos virtuales, etc.
00137         char tmp[ sizeof( *this ) ];
00138         memcpy( tmp,   o,     sizeof( *this ) ); // tmp = o;
00139         memcpy( o,    *this,  sizeof( *this ) ); // o = *this;
00140         memcpy( *this, tmp,   sizeof( *this ) ); // *this = tmp;
00141     #endif
00142     return *this;
00143 }
00144 
00145 /// Asignación desde un \c "long"
00146 inline rational& rational::operator = (long entero) {
00147     m_num = entero;
00148     m_den = 1;
00149     return *this;
00150 }  // operator =
00151 
00152 /// Multiplica \c "*this" por \c "num"
00153 inline rational& rational::operator *= (const rational& num) {
00154     m_num *= num.m_num;
00155     m_den *= num.m_den;
00156     Simplify();
00157     return *this;
00158 }  // operator *=
00159 
00160 /**  Divide \c "*this" por el valor de \c "num".
00161 
00162     \pre
00163     - (num != 0)
00164 */
00165 inline rational& rational::operator /= (const rational& num) {
00166     m_num *= num.m_den;
00167     m_den *= num.m_num;
00168     Simplify();
00169     return *this;
00170 }  // operator /=
00171 
00172 /// \c "-x"
00173 ///
00174 /// - Menos unario
00175 /// - Calcula y retorna el valor \c "-x"
00176 inline rational rational::operator - () const {
00177     rational tmp = (*this);  // tmp.rational( *this );
00178     tmp.m_num = - tmp.m_num;
00179     return tmp;
00180 }  // operator -
00181 
00182 /// ¿ x == y ?
00183 inline bool operator == (const rational &x, const rational &y) {
00184     return (x.m_num == y.m_num) && (x.m_den == y.m_den);
00185 /*  Nota:
00186     Como los números racionales siempre están simplificados, no puede 
00187     ocurrir que [1/1] está almacenado como [3/3] y en consecuencia
00188     basta comparar los valores campo por campo para determinar si se
00189     da o no la igualdad.
00190 */
00191 }  // operator ==
00192 
00193 /// ¿ x < y ?
00194 inline bool operator < (const rational &x, const rational &y) {
00195     return (x.m_num * y.m_den) < (x.m_den * y.m_num);
00196 /*  Nota:
00197     Una desigualda de fracciones se preservar siempre que se 
00198     multiplique a ambos lados por un número positivo. Por eso:
00199           [a/b] <       [c/d]   <==>
00200     [(b*d)*a/b] < [(b*d)*c/d]   <==>
00201           [d*a] < [b*c]
00202 
00203     [a/b] > [c/d] <==> [(b*d)*a/b] > [(b*d)*c/d] <==> [d*a] > [b*c]
00204 
00205     Debido a que el denominador siempre es un número positivo, el
00206     trabajo de comparar 2 racionales se puede lograr haciendo 2
00207     multiplicaciones de números enteros, en lugar de convertirlos
00208     a punto flotante para hacer la división, que es hasta un orden
00209     de maginitud más lento.
00210 */
00211 }  // operator <
00212 
00213 /// ¿ x > y ?
00214 inline bool operator > (const rational &x, const rational &y) {
00215     return (y < x);
00216 }  // operator >
00217 
00218 /// ¿ x != y ?
00219 inline bool operator != (const rational& x, const rational& y) {
00220     return !(x == y);
00221 }  // operator !=
00222 
00223 /// ¿ x <= y ?
00224 inline bool operator <= (const rational& x, const rational& y) {
00225     return !(y < x);
00226 }  // operator <=
00227 
00228 /// ¿ x >= y ?
00229 inline bool operator >= (const rational& x, const rational& y) {
00230     return !(x < y);
00231 }  // operator >=
00232 
00233 /// Convertidor a punto flotante
00234 inline double real(const rational& num) {
00235     return double (num.m_num) / double (num.m_den);
00236 } // real()
00237 
00238 /// Convertidor a punto fijo
00239 inline long integer(const rational& num) {
00240     return long   (num.m_num /          num.m_den);
00241 } // integer()
00242 
00243 #if 0
00244 inline rational::operator long() {
00245 // Convertidor a punto fijo
00246     return long (m_num / m_den);
00247 }  // rational::operator long
00248 #endif
00249 
00250 bool check_ok_externo( const rational& r );
00251 
00252 CLOSE_namespace(ADH)
00253 
00254 #endif // rational_h
00255 
00256 // EOF: rational.h

Generado el Mon Sep 11 00:19:12 2006 para Herencia Ordenada: por  doxygen 1.4.7
Hosted by www.Geocities.ws

1