먼저 파이썬 인터프리터를 실행하여 0.3 - 0.2 - 0.1 의 계산 결과를 알아 보았습니다.

>>> 0.3 - 0.2 - 0.1
-2.7755575615628914e-17

계산 결과가 왜 0이 아닌 엉뚱한 값 -2.7755575615628914e-17 이 될까요?

 

IEEE754 에 대해서는 관련되는 두 문서

    [1]  Double-precision floating-point format  

    [2]  Floating Point Arithmetic: Issues and Limitations 

를 참고하기 바랍니다.

 

NET Framework 4.6.x 이상에서 사용가능한 NET용 분수 계산 라이브러리를 소개합니다.

(소스 수정 없이 NET Core 5.0 이상에서도 사용 가능합니다.)

(Mac OS 에서도 FractionLib 를 빌드하여 쓸 수 있습니다만, UnitTest 프로젝트는 새로 작성해야 합니다.)

FractionLib project  에서 내려받은 프로젝트 파일을

Vusual Studio 2019 이상에서 빌드하여 생성된 FractionLib.dll을,

다른 프로젝트에서 라이브러리로 참조 사용하면 IEEE754 의 배정밀도 부동소숫점수를

분수로 받아들여 보다 정확한 수치 계산을 할 수 있습니다.

내부적으로 C#의 표준 큰 정수 BigInteger를 이용하므로 System.Numerics,dll을

함께 참조 추가하면 더 좋습니다.

FractionLib,dll을 사용할 수 있는 언어로는 C# 언어 외에 F#, Visual Basic, IronPython, C++/CLI

언어들도 가능합니다.

사용 예제는 위 프로젝트의 Examples 폴더에 있습니다.

 

부동소수점수의 뺄셈 계산

      0.3 - 0.2 - 0.1

의 계산 결과는 당연히 0이 되어야 함에도 불구하고 

IEEE 754에서 정한 부동소수점수의 한계(mantissa, 유효숫지 부분의 한계)

때문에 0.3 - 0.2 - 0.1 의 계산 결과가 0이 아닌 적당한 근사값로 계산되며,

그 역수는  -1.0E20 보다 큰 음수로 계산됩니다.

그러나 FractionLib.dll 을 사용하여

 

using knumerics;

    ......................
    ......................

    MyFraction a3 = new MyFraction(0.3);
    MyFraction a2 = new MyFraction(0.2);
    MyFraction a1 = new MyFraction(0.1); 
    MyFraction zero = new MyFraction(0, 1);
    
    MyFraction result = a3 - a2 - a1;
    Console.WriteLine("result == zero ? {0}", result == zero);

 

로 작상하면 0.3 - 0.2 - 0.1의 계산 결과가 정확히 0이 됩니다.

 

참고로, 온라인 상에서 Python 언어, C# 언어, C 언어로 각각 테스트해 보았습니다.

 

Python 언어로 0.3 - 0.2 - 0.1 계산하기

 

C# 언어로 0.3 - 0.2 - 0.1 계산하기

 

 

C 언어로 0.3 - 0.2 - 0.1 계산하기

 

Posted by Scripter
,

* Mathemaica 로 연습해본 분수 계산



* C++ 언어로 구현해본 분수 계산 예제 소스
   (참고1: 0으로 나누는 예외상황, 0의 음수 지수 예외상황 처리됨)
   (참고2: VC++ 와 g++ 로 모두 컴파일되고 실행됨)

/**
 * Filename TestFraction.cpp
 *
 *      Version: 0.4
 *      Purpose: Calculate fractions.
 *
 *  With VC++
 *      Compile: cl TestFraction.cpp /EHsc
 *      Execute: TestFraction
 *
 *  With g++
 *      Compile: g++ TestFraction.cpp -o TestFraction
 *      Execute: ./TestFraction
 *
 *  Date: 2011. 10. 9 (Sun)
 */

#include <iostream>
#include <cmath>
#include <cstring>

using namespace std;

class Fraction {
private:
    long numer, denom;
public:
    Fraction(long _x = 0L, long _y = 1L): numer(_x), denom(_y) {
        if (denom < 0) {
          simplify();
        }
     }
    ~Fraction() {
    }
    Fraction copy();
    void simplify();
    void setNumer(long v);
    void setDenom(long v);
    void set(long a, long b);
    long getNumer();
    long getDenom();
    long *get();
    Fraction operator+(const Fraction &other);
    Fraction operator+(long other);
    Fraction operator-(const Fraction &other);
    Fraction operator-(long other);
    Fraction operator/(Fraction other);
    Fraction operator/(long other);
    Fraction operator-();
    Fraction operator^(long other);
    bool operator==(const Fraction &b);
    bool operator<(const Fraction &b);
    bool operator<=(const Fraction &b);
    bool operator>(const Fraction &b);
    bool operator>=(const Fraction &b);
    bool operator==(long double v);
    bool operator<(long double v);
    bool operator<=(long double v);
    bool operator>(long double v);
    bool operator>=(long double v);
    bool isZero();
    long double eval();
    void show();
};

long gcd(long a, long b) {
    long tmp, q, r;
    q = abs(a);
    r = abs(b);
    while (r > 0) {
       tmp = q % r;
       q = r;
       r = tmp;
    }
    return q;
}

Fraction Fraction::copy() {
 Fraction tmp(0, 1);
 tmp.numer = numer;
 tmp.denom = denom;
 return tmp;
}

void Fraction::simplify() {
    long x = abs(numer);
    long y = abs(denom);
    long d = gcd(x, y);
    if (denom < 0) {
     numer = -numer/d;
     denom = -denom/d;
    }
    else {
     numer = numer/d;
     denom = denom/d;
    }
}

long double Fraction::eval() {
    long double tmp  = ((long double) numer)/((long double) denom);
    return tmp;
}

void Fraction::show() {
    if (denom == 1)
        cout << numer << endl;
    else
        cout << "(" << numer << "/" << denom << ")" << endl;
}

bool Fraction::isZero() {
    return numer == 0;
}

void printFraction(const char *msg, Fraction a) {
 if (msg == NULL || strlen(msg) == 0) {
        cout << "(" << a.getNumer() << "/" << a.getDenom() << ")" << endl;
 }
 else {
        cout << msg << "(" << a.getNumer() << "/" << a.getDenom() << ")" << endl;
 }
}

void Fraction::setNumer(long v) {
 numer = v;
}

void Fraction::setDenom(long v) {
 denom = v;
}

void Fraction::set(long a, long b) {
 numer = a;
 denom = b;
}

long Fraction::getNumer() {
 return numer;
}

long Fraction::getDenom() {
 return denom;
}

long *Fraction::get() {
 static long tmp[2];
 tmp[0] = getNumer();
 tmp[1] = getDenom();
 return (long *)tmp;
}


Fraction Fraction::operator+(const Fraction &other) {
    long x = numer*other.denom + denom*other.numer;
    long y = denom*other.denom;
    long d = gcd(x, y);
    Fraction tmp(x/d, y/d);
    return tmp;
}

Fraction Fraction::operator+(long other) {
    long x = numer + denom*other;
    long y = denom;
    long d = gcd(x, y);
    Fraction tmp(x/d, y/d);
    return tmp;
}

Fraction operator+(long other, Fraction a) {
    long x = a.getNumer() + a.getDenom()*other;
    long y = a.getDenom();
    long d = gcd(x, y);
    Fraction tmp(x/d, y/d);
    return tmp;
}

Fraction Fraction::operator-(const Fraction &other) {
    long x = numer*other.denom - denom*other.numer;
    long y = denom*other.denom;
    long d = gcd(x, y);
    Fraction tmp(x/d, y/d);
    return tmp;
}

Fraction Fraction::operator-(long other) {
    long x = numer - denom*other;
    long y = denom;
    long d = gcd(x, y);
    Fraction tmp(x/d, y/d);
    return tmp;
}

Fraction operator-(long other, Fraction a) {
    long x = a.getDenom()*other - a.getNumer();
    long y = a.getDenom();
    long d = gcd(x, y);
    Fraction tmp(x/d, y/d);
    return tmp;
}

Fraction operator*(long other, Fraction a) {
    long x = a.getNumer()*other;
    long y = a.getDenom();
    long d = gcd(x, y);
    Fraction tmp(x/d, y/d);
    return tmp;
}

Fraction operator*(Fraction a, Fraction b) {
    long x = a.getNumer()*b.getNumer();
    long y = a.getDenom()*b.getDenom();
    long d = gcd(x, y);
    Fraction tmp(x/d, y/d);
    return tmp;
}

Fraction Fraction::operator/(Fraction other) {
 try {
      if (other.isZero()) {
     throw "Divided by zero.";
    }
        long x = numer*other.getDenom();
        long y = denom*other.getNumer();
        long d = gcd(x, y);
        Fraction tmp(x/d, y/d);
        return tmp;
 }
 catch (const char *msg) {
  cout << "Exception: " << msg << endl;
  return NULL;
 }
}

Fraction Fraction::operator-() {
    long x = -numer;
    long y = denom;
    long d = gcd(x, y);
    Fraction tmp(x/d, y/d);
    return tmp;
}

Fraction Fraction::operator^(long n) {
  try {
  if (n <= 0 && numer == 0) {
     throw "Nonpositive power of zero does not exist.";
    }
     Fraction one(1, 1);
     Fraction tmp;
     if (n == 0) {
         tmp.setNumer(1);
         tmp.setDenom(1);
         return tmp;
     }
     else if (n == 1) {
         tmp.setNumer(numer);
         tmp.setDenom(denom);
         return tmp;
     }
     else {
         long mn = n;
         if (mn < 0)
             mn = -mn;
         tmp.setNumer(numer);
         tmp.setDenom(denom);
         tmp = tmp.operator^(mn/2);
         if (mn % 2 == 1) {
             tmp.setNumer(tmp.getNumer()*tmp.getNumer()*numer);
             tmp.setDenom(tmp.getDenom()*tmp.getDenom()*denom);
         }
         else {
             tmp.setNumer(tmp.getNumer()*tmp.getNumer());
             tmp.setDenom(tmp.getDenom()*tmp.getDenom());
         }
         if (n < 0) {
             long t;
             t = tmp.numer;
             if (t < 0) {
                 tmp.setNumer(-tmp.getDenom());
                 tmp.setDenom(-t);
             }
             else {
                 tmp.setNumer(tmp.getDenom());
                 tmp.setDenom(t);
             }
         }
         return tmp;
      }
  }
  catch (const char *msg) {
   cout << "Exception: " << msg << endl;
   return NULL;
  }
}

bool Fraction::operator==(const Fraction &b) {
    return numer*b.denom == denom*b.numer;
}

bool Fraction::operator<(const Fraction &b) {
    return numer*b.denom < denom*b.numer;
}

bool Fraction::operator<=(const Fraction &b) {
    return numer*b.denom <= denom*b.numer;
}

bool Fraction::operator>(const Fraction &b) {
    return numer*b.denom > denom*b.numer;
}

bool Fraction::operator>=(const Fraction &b) {
    return numer*b.denom >= denom*b.numer;
}

bool Fraction::operator==(long double v) {
    return eval() - v == 0;
}

bool Fraction::operator<(long double v) {
    return eval() < v;
}

bool Fraction::operator<=(long double v) {
    return eval() <= v;
}

bool Fraction::operator>(long double v) {
    return eval() > v;
}

bool Fraction::operator>=(long double v) {
    return eval() >= v;
}

int main() {
    Fraction a(1, 6);
    printFraction("a = ", a);

    Fraction b(3, 4);
    printFraction("b = ", b);

    Fraction c = a + b;
    printFraction("c = a + b = ", c);

    c = a - b;
    printFraction("c = a - b = ", c);

    c = a * b;
    printFraction("c = a * b = ", c);

    c = a / b;
    printFraction("c = a / b = ", c);

    printFraction("-a = ", -a);
    printFraction("a + 1 = ", a + 1);
    printFraction("1 + a = ", 1 + a);
    printFraction("a - 1 = ", a - 1);
    printFraction("1 - a = ", 1 - a);
    printFraction("a * 2 = ", a * 2);
    printFraction("-3 * a = ", -3 * a);
    printFraction("1 + a - 3 = ", 1 + a - 3);
    printFraction("a^2 = ", a^2);
    printFraction("b^3 = ", b^3);
    printFraction("-b^-3 = ", -b^-3);

    c = a.copy();
    printFraction("a = ", a);
    printFraction("b = ", b);
    printFraction("c = ", c);
    cout << "    a == c ? " << (a == c) << endl;
    cout << "    a < c ? " << (a < c) << endl;
    cout << "    a <= c ? " << (a <= c) << endl;
    cout << "    a > c ? " << (a > c) << endl;
    cout << "    a >= c ? " << (a >= c) << endl;
    cout << "    a == b ? " << (a == b) << endl;
    cout << "    a < b ? " << (a < b) << endl;
    cout << "    a <= b ? " << (a <= b) << endl;
    cout << "    a > b ? " << (a > b) << endl;
    cout << "    a >= b ? " << (a >= b) << endl;

    a.setNumer(3);
    cout << "Comapre again!" << endl;
    printFraction("a = ", a);
    printFraction("c = ", c);
    cout << "    a == c ? " << (a == c) << endl;

    Fraction d(5, -10);
    printFraction("d = ", d);

    printFraction("a = ", a);
    a.simplify();
    printFraction("Simplified, a = ", a);
    cout << " a.eval() = " << a.eval() << endl;
   
    int i;
    long *pval;
    printFraction("a = ", a);
    pval = a.get();
    for (i = 0; i < 2; i++) {
        cout << " pval[" << i << "] = " << pval[i] << endl;
    }
    printFraction("c = ", c);
    pval = c.get();
    for (i = 0; i < 2; i++) {
        cout << " pval[" << i << "] = " << pval[i] << endl;
    }
    printFraction("d = ", d);
    pval = d.get();
    for (i = 0; i < 2; i++) {
        cout << " pval[" << i << "] = " << pval[i] << endl;
    }
   
    printFraction("a = ", a);
    cout << "    a == 0.1 ? " << (a == 0.1) << endl;
    cout << "    a < 0.1 ? " << (a < 0.1) << endl;
    cout << "    a <= 0.1 ? " << (a <= 0.1) << endl;
    cout << "    a > 0.1 ? " << (a > 0.1) << endl;
    cout << "    a >= 0.1 ? " << (a >= 0.1) << endl;
   
    Fraction e = a/(b - b);
    printFraction("e = ", e);

    e = (b - b)^-2;
    printFraction("e = ", e);

    return 0;
}

/*
a = (1/6)
b = (3/4)
c = a + b = (11/12)
c = a - b = (-7/12)
c = a * b = (1/8)
c = a / b = (2/9)
-a = (-1/6)
a + 1 = (7/6)
1 + a = (7/6)
a - 1 = (-5/6)
1 - a = (5/6)
a * 2 = (1/3)
-3 * a = (-1/2)
1 + a - 3 = (-11/6)
a^2 = (1/36)
b^3 = (27/64)
-b^-3 = (-64/27)
a = (1/6)
b = (3/4)
c = (1/6)
    a == c ? 1
    a < c ? 0
    a <= c ? 1
    a > c ? 0
    a >= c ? 1
    a == b ? 0
    a < b ? 1
    a <= b ? 1
    a > b ? 0
    a >= b ? 0
Comapre again!
a = (3/6)
c = (1/6)
    a == c ? 0
d = (-1/2)
a = (3/6)
Simplified, a = (1/2)
 a.eval() = 0.5
a = (1/2)
 pval[0] = 1
 pval[1] = 2
c = (1/6)
 pval[0] = 1
 pval[1] = 6
d = (-1/2)
 pval[0] = -1
 pval[1] = 2
a = (1/2)
    a == 0.1 ? 0
    a < 0.1 ? 0
    a <= 0.1 ? 0
    a > 0.1 ? 1
    a >= 0.1 ? 1
Exception: Divided by zero.
e = (0/1)
Exception: Nonpositive power of zero does not exist.
e = (0/1)
*/







* Groovy 언어로 작성된 분수 계산용 Fraction 클래스 (Java에서도 사용 가능)
   (참고: Groovy 1.8.0 & Java 7 및 Groovy 1.8.2 & Java 7 에소 테스트되었음)

/**********************************************************************************
 * Filename: Fraction.groovy
 *
 *  Purpose:
 *           A class, supporting fraction calculations,
 *           which depends on the long types of Java.
 *
 *  Setting Environment Variables:
 *           set JAVA_HOME=c:\Java7
 *           set GROOVY_HOME=c:\groovy182
 *           set PATH=c:%GROOVY_HOME%\bin;%PATH%
 *
 *  Execute Only: groovy Fraction.groovy
 *  Compile for Java: groovyc -d . Fraction.groovy
 *
 *    Author: Copyright (c) 2011. 10. 7 (Fri)  PH Kim  ( pkim (AT) scripts (DOT) pe (DOT) kr )
 ***********************************************************************************/

package kr.pe.scripts.numeric.fraction

public class Fraction {

    public long numer;
    public long denom;

    final public static Fraction ZERO = new Fraction(0, 1);
    final public static Fraction ONE = new Fraction(1, 1);
    final public static Fraction TWO = new Fraction(2, 1);
    final public static Fraction THREE = new Fraction(3, 1);
    final public static Fraction TEN = new Fraction(10, 1);

    public Fraction(long numer, long denom) {
        this.numer = numer;
        this.denom = denom;
    }

    public boolean isZero() {
         return this.numer == 0L;
    }

    public Fraction plus(Fraction other) {
         long a = this.numer*other.denom + this.denom*other.numer;
         long b = this.denom*other.denom;
         Fraction z = new Fraction(a, b);
         z.simplify();
         return z;
    }

    public Fraction minus(Fraction other) {
         long a = this.numer*other.denom - this.denom*other.numer;
         long b = this.denom*other.denom;
         Fraction z = new Fraction(a, b);
         simplify(z);
         return z;
    }

    public Fraction multiply(Fraction other) {
         long a = this.numer*other.numer;
         long b = this.denom*other.denom;
         if (b < 0) {
             a = -a;
             b = -b;
         }
         Fraction z = new Fraction(a, b);
         simplify(z);
         return z;
    }

    public Fraction div(Fraction other) {
         if (other.isZero()) {
             throw new RuntimeException("Cannot divide by the fraction " + other + ", since it is zero.");
         }
         long a = this.numer*other.denom;
         long b = this.denom*other.numer;
         if (b < 0) {
             a = -a;
             b = -b;
         }
         Fraction z = new Fraction(a, b);
         simplify(z);
         return z;
    }

    public void simplify() {
        long c = gcd(this.numer, this.denom);
        // if (c < 0)
        //     c = -c;
        this.numer = (this.numer / c) as long;
        this.denom = (this.denom / c) as long;
        if (this.numer == 0) {
            this.denom = 1;
        }
    }

    public static void simplify(Fraction z) {
        long c = gcd(z.numer, z.denom);
        z.numer = (z.numer / c) as long;
        z.denom = (z.denom / c) as long;
        if (z.numer == 0) {
            z.denom = 1;
        }
    }

    public static long gcd(long a, long b) {
        long q = Math.abs(a);
        long r = Math.abs(b);
        long t;
        while (r != 0L) {
           t = r;
           r = q % r
           q = t;
        }
        return q;
    }

    /*
    public Complex power(long n) {
         long mn = n;
         if (mn < 0.0)
             mn = -mn;
         Complex tmp = new Complex(1, 0);
         for (int i = 0; i < mn; i++) {
             tmp = tmp*this;
         }
         if (n < 0) {
             tmp = new Complex(1, 0) / tmp;
         }
         return tmp;
    }
    */

    public Fraction power(long n) {
         if (n < 0 && this.isZero()) {
             throw new RuntimeException("Negative power of " + this + " dose not exist, since it is zero.");
         }
         if (n == 0)
             return new Fraction(1, 1);
         else if (n == 1)
             return new Fraction(this.numer, this.denom);
         long mn = n;
         if (mn < 0L)
             mn = -mn;
         Fraction tmp = this.power((mn/2) as long);
         if (mn % 2 == 1) {
             tmp = tmp*tmp*this;
         }
         else {
             tmp = tmp*tmp;
         }
         if (n < 0) {
             // println("    : tmp = " + tmp);
             tmp = Fraction.ONE / tmp;
             // println("        ----> tmp = " + tmp);
         }
         return tmp;
    }

    public static Fraction square(Fraction z) {
         return z*z;
    }

    public static Fraction cube(Fraction z) {
         return z*z*z;
    }

    public Fraction inverse() {
        if (this.isZero()) {
             throw new RuntimeException("The multiplicative inverse of " + this + " does not exist, since it is zero.");
         }
         if (this.numer < 0)
             return new Fraction(-this.denom, -this.numer);
         else
             return new Fraction(this.denom, this.numer);
    }

    public Fraction abs() {
        return new Fraction(Math.abs(this.numer), this.denom)
    }

    public static Fraction abs(Fraction z) {
        return new Fraction(Math.abs(z.numer), z.denom)
    }

    public Fraction negative() {
        return new Fraction(-this.numer, this.denom)
    }

    public boolean equals(Fraction other) {
        return this.numer*other.denom == other.numer*this.denom;
    }

    public String toString() {
        if (this.denom == 1)
            return "" + this.numer;
        return "(" + this.numer + "/" + this.denom + ")";
    }

    public static void println(String s) {
        System.out.println(s);
    }

    public static void main(String[] args) {
        Fraction z = new Fraction(1, 2);
        Fraction w = new Fraction(5, 4);
        println("z = " + z);
        println("w = " + w);
        println("    z + w = " + (z + w));
        println("    z - w = " + (z - w));
        println("    z * w = " + (z * w));
        println("    z / w = " + (z / w));
        println("    z**2 = " + (z**2));
        println("    z**3 = " + (z**3));
        println("    z.inverse() = " + z.inverse());
        println("    1/z = " + (ONE/z));
        println("    z**-1 = " + (z**-1));
        println("    z**-2 = " + (z**-2));
        println("    z**-3 = " + (z**-3));
        println("    -z = " + (-z));
        println("    z.abs() = (" + z + ").abs() = " + z.abs());
        println("    z == " + new Fraction(1, 2) + " ? " + (z == new Fraction(1,2)));
        println("    z - z = " + (z - z));
        println("    (z - z).isZero() ? " + (z - z).isZero());
        println("    Fraction.ZERO = " + Fraction.ZERO);
        println("    Fraction.ONE = " + Fraction.ONE);
        println("    Fraction.TWO = " + Fraction.TWO);
        println("    Fraction.THREE = " + Fraction.THREE);
        println("    Fraction.TEN = " + Fraction.TEN);
        println("  z = " + z);
        println("  w.negative() = " + w.negative());
        println("    z**0 = " + (z**0));
        println("    z**1 = " + (z**1));
        println("    z**2 = " + (z**2));
        println("    z**3 = " + (z**3));
        println("    z**4 = " + (z**4));
        println("    z**10 = " + (z**10));
        println("    z**-1 = " + (z**-1));
        println("    z**-2 = " + (z**-2));
        println("    z**-3 = " + (z**-3));
        println("    z**-4 = " + (z**-4));
        println("    z**-10 = " + (z**-10));
        println("    w.negative()**0 = " + (w.negative()**0));
        println("    w.negative()**1 = " + (w.negative()**1));
        println("    w.negative()**2 = " + (w.negative()**2));
        println("    w.negative()**3 = " + (w.negative()**3));
        println("    w.negative()**4 = " + (w.negative()**4));
        println("    w.negative()**10 = " + (w.negative()**10));
        println("    w.negative()**-1 = " + (w.negative()**-1));
        println("    w.negative()**-2 = " + (w.negative()**-2));
        println("    w.negative()**-3 = " + (w.negative()**-3));
        println("    w.negative()**-4 = " + (w.negative()**-4));
        println("    w.negative()**-10 = " + (w.negative()**-10));
        println("    (z - w)**0 = " + ((z - w)**0));
        println("    (z - w)**1 = " + ((z - w)**1));
        println("    (z - w)**2 = " + ((z - w)**2));
        println("    (z - w)**3 = " + ((z - w)**3));
        println("    (z - w)**-1 = " + ((z - w)**-1));
        println("    (z - w)**-2 = " + ((z - w)**-2));
        println("    (z - w)**-3 = " + ((z - w)**-3));
    }
}

/*
Execution Result:
z = (1/2)
w = (5/4)
    z + w = (7/4)
    z - w = (-3/4)
    z * w = (5/8)
    z / w = (2/5)
    z**2 = (1/4)
    z**3 = (1/8)
    z.inverse() = 2
    1/z = 2
    z**-1 = 2
    z**-2 = 4
    z**-3 = 8
    -z = (-1/2)
    z.abs() = ((1/2)).abs() = (1/2)
    z == (1/2) ? true
    z - z = 0
    (z - z).isZero() ? true
    Fraction.ZERO = 0
    Fraction.ONE = 1
    Fraction.TWO = 2
    Fraction.THREE = 3
    Fraction.TEN = 10
  z = (1/2)
  w.negative() = (-5/4)
    z**0 = 1
    z**1 = (1/2)
    z**2 = (1/4)
    z**3 = (1/8)
    z**4 = (1/16)
    z**10 = (1/1024)
    z**-1 = 2
    z**-2 = 4
    z**-3 = 8
    z**-4 = 16
    z**-10 = 1024
    w.negative()**0 = 1
    w.negative()**1 = (-5/4)
    w.negative()**2 = (25/16)
    w.negative()**3 = (-125/64)
    w.negative()**4 = (625/256)
    w.negative()**10 = (9765625/1048576)
    w.negative()**-1 = (-4/5)
    w.negative()**-2 = (16/25)
    w.negative()**-3 = (-64/125)
    w.negative()**-4 = (256/625)
    w.negative()**-10 = (1048576/9765625)
    (z - w)**0 = 1
    (z - w)**1 = (-3/4)
    (z - w)**2 = (9/16)
    (z - w)**3 = (-27/64)
    (z - w)**-1 = (-4/3)
    (z - w)**-2 = (16/9)
    (z - w)**-3 = (-64/27)
*/




* Groovy 언어로 작성된 Fraction 클래스를 테스트하는 Java 예제 소스
   (참고: Groovy 1.8.0 & Java 7 및 Groovy 1.8.2 & Java 7 에서 테스트되었음)

/**********************************************************************************
 * Filename: TestFraction.java
 *
 *  Purpose:
 *           Testing the Fraction class made by Groovy,
 *
 *  Setting Environment Variables:
 *           set JAVA_HOME=c:\Java7
 *           set GROOVY_HOME=c:\groovy182
 *           set PATH=c:%GROOVY_HOME%\bin;%PATH%
 *
 *  Compile: javac -d . TestFraction.java
 *  Execute: java -cp .;%GROOVY_HOME%\embeddable\groovy-all-1.8.2.jar
 *                kr.pe.scripts.numeric.fraction.TestFraction
 *
 *    Author: Copyright (c) 2011. 10. 7 (Fri)  PH Kim  ( pkim (AT) scripts (DOT) pe (DOT) kr )
 ***********************************************************************************/

package kr.pe.scripts.numeric.fraction;

import kr.pe.scripts.numeric.fraction.Fraction;

public class TestFraction {

    public static void println(String s) {
        System.out.println(s);
    }

    public static void main(String[] args) {
        Fraction z = new Fraction(1, 2);
        Fraction w = new Fraction(5, 4);
        println("z = " + z);
        println("w = " + w);
        println("    z + w = " + z.plus(w));
        println("    z - w = " + z.minus(w));
        println("    z * w = " + z.multiply(w));
        println("    z / w = " + z.div(w));
        println("    z**2 = " + z.power(2));
        println("    z**3 = " + z.power(3));
        println("    z.inverse() = " + z.inverse());
        println("    1/z = " + Fraction.ONE.div(z));
        println("    z**-1 = " + z.power(-1));
        println("    z**-2 = " + z.power(-2));
        println("    z**-3 = " + z.power(-3));
        println("    -z = " + z.negative());
        println("    z.abs() = (" + z + ").abs() = " + z.abs());
        println("    z == " + new Fraction(1, 2) + " ? " + (z == new Fraction(1,2)));
        println("    z - z = " + z.minus(z));
        println("    (z - z).isZero() ? " + z.minus(z).isZero());
        println("    Fraction.ZERO = " + Fraction.ZERO);
        println("    Fraction.ONE = " + Fraction.ONE);
        println("    Fraction.TWO = " + Fraction.TWO);
        println("    Fraction.THREE = " + Fraction.THREE);
        println("    Fraction.TEN = " + Fraction.TEN);
        println("  z = " + z);
        println("  w.negative() = " + w.negative());
        println("    z**0 = " + z.power(0));
        println("    z**1 = " + z.power(1));
        println("    z**2 = " + z.power(2));
        println("    z**3 = " + z.power(3));
        println("    z**4 = " + z.power(4));
        println("    z**10 = " + z.power(10));
        println("    z**-1 = " + z.power(-1));
        println("    z**-2 = " + z.power(-2));
        println("    z**-3 = " + z.power(-3));
        println("    z**-4 = " + z.power(-4));
        println("    z**-10 = " + z.power(-10));
        println("    w.negative()**0 = " + w.negative().power(0));
        println("    w.negative()**1 = " + w.negative().power(1));
        println("    w.negative()**2 = " + w.negative().power(2));
        println("    w.negative()**3 = " + w.negative().power(3));
        println("    w.negative()**4 = " + w.negative().power(4));
        println("    w.negative()**10 = " + w.negative().power(10));
        println("    w.negative()**-1 = " + w.negative().power(-1));
        println("    w.negative()**-2 = " + w.negative().power(-2));
        println("    w.negative()**-3 = " + w.negative().power(-3));
        println("    w.negative()**-4 = " + w.negative().power(-4));
        println("    w.negative()**-10 = " + w.negative().power(-10));
        println("    (z - w)**0 = " + z.minus(w).power(0));
        println("    (z - w)**1 = " + z.minus(w).power(1));
        println("    (z - w)**2 = " + z.minus(w).power(2));
        println("    (z - w)**3 = " + z.minus(w).power(3));
        println("    (z - w)**-1 = " + z.minus(w).power(-1));
        println("    (z - w)**-2 = " + z.minus(w).power(-2));
        println("    (z - w)**-3 = " + z.minus(w).power(-3));
    }
}

/*
Execution Result:
z = (1/2)
w = (5/4)
    z + w = (7/4)
    z - w = (-3/4)
    z * w = (5/8)
    z / w = (2/5)
    z**2 = (1/4)
    z**3 = (1/8)
    z.inverse() = 2
    1/z = 2
    z**-1 = 2
    z**-2 = 4
    z**-3 = 8
    -z = (-1/2)
    z.abs() = ((1/2)).abs() = (1/2)
    z == (1/2) ? false
    z - z = 0
    (z - z).isZero() ? true
    Fraction.ZERO = 0
    Fraction.ONE = 1
    Fraction.TWO = 2
    Fraction.THREE = 3
    Fraction.TEN = 10
  z = (1/2)
  w.negative() = (-5/4)
    z**0 = 1
    z**1 = (1/2)
    z**2 = (1/4)
    z**3 = (1/8)
    z**4 = (1/16)
    z**10 = (1/1024)
    z**-1 = 2
    z**-2 = 4
    z**-3 = 8
    z**-4 = 16
    z**-10 = 1024
    w.negative()**0 = 1
    w.negative()**1 = (-5/4)
    w.negative()**2 = (25/16)
    w.negative()**3 = (-125/64)
    w.negative()**4 = (625/256)
    w.negative()**10 = (9765625/1048576)
    w.negative()**-1 = (-4/5)
    w.negative()**-2 = (16/25)
    w.negative()**-3 = (-64/125)
    w.negative()**-4 = (256/625)
    w.negative()**-10 = (1048576/9765625)
    (z - w)**0 = 1
    (z - w)**1 = (-3/4)
    (z - w)**2 = (9/16)
    (z - w)**3 = (-27/64)
    (z - w)**-1 = (-4/3)
    (z - w)**-2 = (16/9)
    (z - w)**-3 = (-64/27)
*/




* Python 언어로 분수 계산하는 예제
  (참고: 파이썬에는 분수 계산용 모듈 fractions 이 기본적으로 있으므로,
            별도로 분수 계산용 클래스를 만들지 않았다.
            from fractions import *
            이 구문만 추가하면 Fraction 클래스를 사용할 수 있다.  )

"""
  Filename: TestFraction.py

            Test fraction calculations, wgich works on Python 2.6 or 2.7.

   Execute: python TestFraction.py
      Date: 2011. 10. 10
"""

from fractions import *

z = Fraction(1, 2)
w = Fraction("5/4")
print "z = %s,   w=%s" % (z, w)
print "z + w = %s" % (z + w)
print "z - w = %s" % (z - w)
print "z * w = %s" % (z * w)
print "z / w = %s" % (z / w)
print "z**2 = %s" % (z**2)
print "z**3 = %s" % (z**3)
print "1/z = %s" % (1/z)
print "z**-1 = %s" % (z**-1)
print "z**-2 = %s" % (z**-2)
print "z**-3 = %s" % (z**-3)
print "-z = %s" % (-z)
print "abs(z) = %s" % abs(z)
print "z == Fraction(\"1/2\") ? %s" % (z == Fraction("1/2"))
print "z == Fraction(1, 2) ? %s" % (z == Fraction(1, 2))
print "Fraction(3, 6) = %s" % (Fraction(3, 6))
print "z == Fraction(3, 6) ? %s" % (z == Fraction(3, 6))
print "z - z == 0 ? %s" % (z - z == 0)
print "(z - w)**0 = %s" % ((z - w)**0)
print "(z - w)**1 = %s" % ((z - w)**1)
print "(z - w)**2 = %s" % ((z - w)**2)
print "(z - w)**3 = %s" % ((z - w)**3)
print "(z - w)**-1 = %s" % ((z - w)**-1)
print "(z - w)**-2 = %s" % ((z - w)**-2)
print "(z - w)**-3 = %s" % ((z - w)**-3)

"""
Execute Result:
z = 1/2,   w=5/4
z + w = 7/4
z - w = -3/4
z * w = 5/8
z / w = 2/5
z**2 = 1/4
z**3 = 1/8
1/z = 2
z**-1 = 2
z**-2 = 4
z**-3 = 8
-z = -1/2
abs(z) = 1/2
z == Fraction("1/2") ? True
z == Fraction(1, 2) ? True
Fraction(3, 6) = 1/2
z == Fraction(3, 6) ? True
z - z == 0 ? True
(z - w)**0 = 1
(z - w)**1 = -3/4
(z - w)**2 = 9/16
(z - w)**3 = -27/64
(z - w)**-1 = -4/3
(z - w)**-2 = 16/9
(z - w)**-3 = -64/27
"""






* Lua 언어로 분수 계산을 하기 위한 fraction 클래스 소스

-- fraction 0.1.0
-- Lua 5.1

-- Filename: fraction.lua
--
-- 'fraction' provides common tasks with fractional numbers

-- function fraction.new( numer, denom )
--          returns a fraction number on success, nil on failure
--      numer := numerator
--      denom := denominator
--          e.g. fraction.new( -3, 5 )

-- function fraction.to( arg ); fraction( arg )
--          returns a fraction number on success, nil on failure
--      arg := number or { number,number }
--                    or ( "(-)<number>" and/or "(+/-)<number>/(+/-)<number>" )
--          e.g. 5; {2,3}; "2/3", "2 / 3", "+2/  3", "-5 / 4 "

-- function fraction.parseApart( arg )
--      returns a fraction number on success, nil on failure
--      arg := number or { number, number, number }
--                    or ( "(-)<number>" and/or "(+/-)<number> (+/-)<number>/(+/-)<number>"
--                                       and/or "(+/-)<number> + (+/-)<number>/(+/-)<number>" )
--          e.g. {-2, 3, 5}; "-2 3/5", "-2 + 3/5", "-2 + +3/5"

-- a fraction number is defined as numerator over denomnator
-- fraction number := { numer, denom }
--     this gives fast access to both parts of the number for calculation
--     the access is faster than in a hash table
--     the metatable is just a add on, when it comes to speed, one is faster using a direct function call

-- See: http://scripting.tistory.com
--
-- Licensed under the same terms as Lua itself.
--
-- Author:  PH Kim ( pkim [AT] scripts [DOT] pe [DOT] kr )


--/////////////--
--// fraction //--
--/////////////--

-- link to fraction table
local fraction = {}

-- link to fraction metatable
local fraction_meta = {}

-- fraction.to( arg )
-- return a fraction number on success
-- return nil on failure
local _retone = function() return 1 end
local _retminusone = function() return -1 end


function fraction.to( num )
   -- check for table type
   -- print( type( num ) )
   if type( num ) == "table" then
      -- check for a fractionnumber
      if getmetatable( num ) == fraction_meta then
         return num
      end
      local numer, denom = tonumber( num[1] ), tonumber( num[2] )
      if not denom then
          denim = 1
      end
      -- print(numer, denom)
      if numer and denom then
         local d = gcd(numer, denom)
         if d > 1 then
             numer = numer / d
             denom = denom / d
         end
         if denom < 0 then
            return setmetatable( { -numer, -denom }, fraction_meta )
         else
            return setmetatable( { numer, denom }, fraction_meta )
         end
      end
      return
   end

   -- check for number
   local isnum = tonumber( num )
   if isnum then
      return setmetatable( { isnum, 1 }, fraction_meta )
   end

   -- print( type( num ) )
   if type( num ) == "string" then
      -- print( "   >" .. type( num ) )
      -- check for digits
      -- number chars [%-%+%*%^%d/%*%^%d] 
      -- local numer, denom = string.match( num, "^(%-%+%d+)[ ](%d+)$" )
      local numer, denom = string.match( num, "([%+%-%*%^%d]*%d)[\\/ ]*([%+%-%*%^%d]*%d)[, ]*" )
      -- print(numer, denom)
      -- print( type( num ) )
      if numer and denom then
         numer, denom = tonumber(numer), tonumber(denom)
         -- print("    ", numer, denom)
         local d = gcd(numer, denom)
         if d > 1 then
             numer = numer / d
             denom = denom / d
         end
         -- print("    --->  ", numer, denom)
         if denom < 0 then
            return setmetatable( { -numer, -denom }, fraction_meta )
         else
            return setmetatable( { numer, denom }, fraction_meta )
         end
      elseif numer then
          numer = tonumber(numer)
          return setmetatable( { numer, 1 }, fraction_meta )
      end
   end
   return nil
end


-- fraction( arg )
-- same as fraction.to( arg )
-- set __call behaviour of fraction
setmetatable( fraction, { __call = function( _,num ) return fraction.to( num ) end } )


-- fraction.new( numer, denom )
-- fast function to get a complex number, not invoking any checks
function fraction.new( ... )
   return setmetatable( { ... }, fraction_meta )
end


function fraction.parseApart( num )
   -- check for table type
   -- print( type( num ) )
   if type( num ) == "table" then
      -- check for a fractionnumber
      if getmetatable( num ) == fraction_meta then
         return num
      end
      local ipart, numer, denom = tonumber( num[1] ), tonumber( num[2] ), tonumber( num[3] )
      if not denom then
          denom = 1
      end
      -- print(numer, denom)
      if ipart and numer and denom then
         local d = gcd(numer, denom)
         if d > 1 then
             numer = numer / d
             denom = denom / d
         end
         if denom < 0 then
            numer = numer + ipart*(-denom)
            return setmetatable( { -numer, -denom }, fraction_meta )
         else
            numer = numer + ipart*denom
            return setmetatable( { numer, denom }, fraction_meta )
         end
      elseif numer and denom then
         local d = gcd(numer, denom)
         if d > 1 then
             numer = numer / d
             denom = denom / d
         end
         if denom < 0 then
            return setmetatable( { -numer, -denom }, fraction_meta )
         else
            return setmetatable( { numer, denom }, fraction_meta )
         end
      end
      return
   end

   -- check for number
   local isnum = tonumber( num )
   if isnum then
      return setmetatable( { isnum, 1 }, fraction_meta )
   end

   -- print( type( num ) )
   if type( num ) == "string" then
      -- print( "   >" .. type( num ) )
      -- check for digits
      -- number chars [%-%+%*%^%d %-%+%*%^%d/%-%+%*%^%d] 
      -- local numer, denom = string.match( num, "^(%-%+%d+)[ ](%d+)$" )
      ---- print( num )
      local ipart, numer, denom = string.match( num, "([%+%-%*%^%d]*%d)[$+ ]*([%+%-%*%^%d]*%d)[\\/ ]*([%+%-%*%^%d]*%d)[, ]*" )
      ---- print( ipart, numer, denom )
      -- print(numer, denom)
      -- print( type( num ) )
      if ipart and numer and denom then
         ipart, numer, denom = tonumber(ipart), tonumber(numer), tonumber(denom)
         -- print("    ", numer, denom)
         local d = gcd(numer, denom)
         if d > 1 then
             numer = numer / d
             denom = denom / d
         end
         -- print("    --->  ", numer, denom)
         if denom < 0 then
            numer = numer + ipart*(-denom)
            return setmetatable( { -numer, -denom }, fraction_meta )
         else
            numer = numer + ipart*denom
            return setmetatable( { numer, denom }, fraction_meta )
         end
      elseif numer and denom then
         numer, denom = tonumber(numer), tonumber(denom)
         -- print("    ", numer, denom)
         local d = gcd(numer, denom)
         if d > 1 then
             numer = numer / d
             denom = denom / d
         end
         -- print("    --->  ", numer, denom)
         if denom < 0 then
            return setmetatable( { -numer, -denom }, fraction_meta )
         else
            return setmetatable( { numer, denom }, fraction_meta )
         end
      elseif numer then
          numer = tonumber(numer)
          return setmetatable( { numer, 1 }, fraction_meta )
      end
   end
   return nil
end


function fraction.tostring( x )
   local numer, denom = x[1], x[2]
   -- print(numer, denom)
   ---- print(x)
   if denom == 1 then
      return "" .. numer
   else
      return "(" .. numer .. "/" .. denom .. ")"
   end
end

function fraction.toApart( x )
   local numer, denom = x[1], x[2]
   -- print(numer, denom)
   if denom == 1 then
      return "" .. numer
   else
      local q, r
      q = math.floor(numer/denom)
      r = math.fmod(numer, denom)
      -- print( "   q = " .. q .. ",   r = " .. r )
      if r < 0 then
          q = q - 1
          r = r + denom
      end
      -- print( "   -->  q = " .. q .. ",   r = " .. r )
      if q == 0 then
          return "(" .. numer .. "/" .. denom .. ")"
      else
          return "(" .. q .. "+" .. r .. "/" .. denom .. ")"
      end
   end
end

function fraction.toDecimal( x )
   local numer, denom = x[1], x[2]
   return numer/denom
end

-- fraction.print( cx [, formatstr] )
-- print a fraction number
function fraction.print( ... )
   print( fraction.tostring( ... ) )
end

-- fraction.abs( cx )
-- get the absolute value of a fraction number
function fraction.abs( x )
   return fraction.new(x.numer, x.denom )
end

--// functions returning a new complex number

-- fraction.copy( x )
-- copy fraction number
function fraction.copy( x )
   return setmetatable( { cx[1], cx[2] }, fraction_meta )
end

function fraction.simplify( x )
   local numer = x[1]
   local denom = x[2]
   local d = gcd(numer, denom)
   if d > 1 then
        numer = numer / d
        denom = denom / d
    end
    if denom < 0 then
        x[1] = -numer
        x[2] = -denom
    else
        x[1] = numer
        x[2] = denom
    end
end

function gcd( a, b )
    local tmp
    local q, r = math.abs(a), math.abs(b)
    -- print( "  q : " .. q .. ",  r : " .. r )
    tmp = math.fmod(q, r)      
    while tmp > 0 do
        q = r
        r = tmp
        tmp = math.fmod(q, r)      
        -- print( "   --> q : " .. q .. ",  r : " .. r )
    end
    -- print( "   r = " .. r )
    return r
end

-- fraction.add( x1, x2 )
-- add two numbers; x1 + x2
function fraction.add( x1,x2 )
   local numer = x1[1]*x2[2] + x1[2]*x2[1]
   local denom = x1[2]*x2[2]
   local d = gcd(math.abs(numer), math.abs(denom))
   return setmetatable( { numer/d, denom/d }, fraction_meta )
end

-- fraction.sub( x1, x2 )
-- subtract two numbers; x1 - x2
function fraction.sub( x1, x2 )
   local numer = x1[1]*x2[2] - x1[2]*x2[1]
   local denom = x1[2]*x2[2]
   local d = gcd(math.abs(numer), math.abs(denom))
   return setmetatable( { numer/d, denom/d }, fraction_meta )
end

-- fraction.mul( x1, x2 )
-- multiply two numbers; x1 * x2
function fraction.mul( x1, x2 )
   -- return setmetatable( { x1[1]*x2[1], x1[2]*x2[2] }, fraction_meta )
   local numer = x1[1]*x2[1]
   local denom = x1[2]*x2[2]
   local d = gcd(numer, denom)
   if d > 1 then
        numer = numer / d
        denom = denom / d
    end
    if denom < 0 then
        return setmetatable( { -numer, -denom }, fraction_meta )
    else
        return setmetatable( { numer, denom }, fraction_meta )
    end
end

-- fraction.div( x1, x2 )
-- divide two numbers; x1 / x2
function fraction.div( x1, x2 )
   -- return setmetatable( { x1[1]*x2[2], x1[2]*x2[1] }, fraction_meta )
   local numer = x1[1]*x2[2]
   local denom = x1[2]*x2[1]
   local d = gcd(numer, denom)
   if d > 1 then
       numer = numer / d
       denom = denom / d
   end
   if denom < 0 then
       return setmetatable( { -numer, -denom }, fraction_meta )
   end
       return setmetatable( { numer, denom }, fraction_meta )
end

-- fraction.pow( c, num )
-- get the power of a fraction number
function fraction.pow( x, num )
   return setmetatable( { x[1]^num, x[2]^num }, fraction_meta )
end

-- function fraction.lt_event( x1, x2 )
--    print("  --- ", type(x1), type(x2))
--    return fraction_meta.__lt( x1, x2 )
-- end


--// metatable functions

fraction_meta.__add = function( x1, x2 )
   local x1, x2 = fraction.to( x1 ), fraction.to( x2 )
   return fraction.add( x1, x2 )
end

fraction_meta.__sub = function( x1, x2 )
   local x1, x2 = fraction.to( x1 ), fraction.to( x2 )
   return fraction.sub( x1, x2 )
end

fraction_meta.__mul = function( x1, x2 )
   local x1, x2 = fraction.to( x1 ), fraction.to( x2 )
   return fraction.mul( x1, x2 )
end

fraction_meta.__div = function( x1, x2 )
   local x1, x2 = fraction.to( x1 ), fraction.to( x2 )
   return fraction.div( x1, x2 )
end

fraction_meta.__pow = function( x, num )
   local x = fraction.to( x )
   return fraction.pow( x, num )
end

fraction_meta.__unm = function( x )
   -- print("called  UNM here!" )
   return setmetatable( { -x[1], x[2] }, fraction_meta )
end

fraction_meta.__eq = function( x1, x2 )
   -- print("called here!" )
   return x1[1]*x2[2] - x1[2]*x2[1] == 0
end

fraction_meta.__lt = function( x1, x2 )
   return x1[1]*x2[2] - x1[2]*x2[1] < 0
end

fraction_meta.__ltt = function( x1, x2 )
   local x1, x2 = fraction.to( x1 ), fraction.to( x2 )
   print(type(x1), type(x2))
   print(type(x1) == "number", type(x2) == "number")
   if type(x2) == "number" then
       return x1[1] - x1[2]*x2 < 0
   elseif type(x1) == "number" then
       return x1*x2[2] - x2[1] < 0
   end
   return x1[1]*x2[2] - x1[2]*x2[1] < 0
end

fraction_meta.__gt = function( x1, x2 )
   return x1[1]*x2[2] - x1[2]*x2[1] > 0
end

fraction_meta.__le = function( x1, x2 )
   return x1[1]*x2[2] - x1[2]*x2[1] <= 0
end

fraction_meta.__ge = function( x1, x2 )
   return x1[1]*x2[2] - x1[2]*x2[1] >= 0
end

fraction_meta.__tostring = function( x )
   return tostring( fraction.tostring( x ) )
end

fraction_meta.__concat = function( x, x2 )
   return tostring(x)..tostring(x2)
end

fraction_meta.__call = function( ... )
   print( fraction.tostring( ... ) )
end

fraction_meta.__index = {}
for k,v in pairs( fraction ) do
   fraction_meta.__index[k] = v
end

return fraction





** 위의 fraction 클래스를 테스트하는 Lua 예제

--// Filename: TestFraction-01.lua
--//               Using the 'fraction' class given at http://scripting.tistory.com
--//  Execute:  lua TestFraction-01.lua

local fraction = require "fraction"

function printFraction(msg, a)
    if type(msg) == "string" and #(msg) > 0 then
        print( msg .. a )
    else
        print( a )
    end
end

function fraction:eq_event (x1, x2)
   print("... eq_event() called here!" )
   if x1[1]*x2[2] - x1[2]*x2[1] == 0 then
      return true
   else
       return false
   end
end

local a, b, c, d

-- instantiate of matrices
a = fraction.new(6, 9)
printFraction( "a = ", a )
fraction.simplify( a )
printFraction( "Simplified, a = ", a )
b = fraction {120, 150}
printFraction( "b = ", b )
fraction.simplify( b )
printFraction( "Simplified, b = ", b )
-- c = fraction"2/5"
c = fraction"-2 / 5"
printFraction( "c = ", c )
printFraction( "-c = ", -c )
printFraction( "5 - c = ", 5 - c )
printFraction( "5 + c - 2 = ", 5 + c - 2 )
printFraction( "3*c = ", 3*c )
printFraction( "2/c = ", 2/c )
print( 3 - fraction"1/10" - 1 )
print( fraction"3" - fraction"1/10" + fraction"-1" )
print( fraction {-3, -1} - fraction {1, 10} + fraction {-1, 1} )
print( fraction"-5/-10" )
printFraction( "a^2 = ", a^2 )
printFraction( "1/a = ", 1/a )
printFraction( "1/a^2 = ", 1/a^2 )
printFraction( "a = ", a )
printFraction( "b = ", b )
printFraction( "b/a = ", b/a )
printFraction( "b/a^2 = ", b/a^2 )
print( "fraction.toApart(b/a^2) = " .. fraction.toApart(b/a^2) )
print( "fraction.toDecimal(b/a^2) = " .. fraction.toDecimal(b/a^2) )
printFraction( "-b/a^2 = ", -b/a^2 )
print( "fraction.toApart(-b/a^2) = " .. fraction.toApart(-b/a^2) )
print( "fraction.toDecimal(-b/a^2) = " .. fraction.toDecimal(-b/a^2) )
a = fraction.new(12, 6)
printFraction( "Changed, a = ", a )
printFraction( "a[1] = ", a[1] )
printFraction( "a[2] = ", a[2] )
print( "a == b ?", a == b )
print( "a ~= b ?", a ~= b )
print( "a == fraction\"2\" ?", a == fraction"2" )
print( "a ~= fraction\"2\" ?", a ~= fraction"2" )
print( "not (a == fraction\"2\") ?", not (a == fraction"2") )
print( "a < b ?", a < b )
print( "a < fraction\"2\" ?", a < fraction"2" )
print( "fraction\"2\" > a ?", fraction"2" > a )
print( "a > fraction\"2\" ?", a > fraction"2" )
print( "a > b ?", a > b )
print( "a <= b ?", a <= b )
print( "a >= b ?", a >= b )
print( "a <= fraction\"2\" ?", a <= fraction"2" )
print( "a >= fraction\"2\" ?", a >= fraction"2" )
print( "a <= fraction.to(2) ?", a <= fraction.to(2) )
print( "a >= fraction.to(2) ?", a >= fraction.to(2) )
print( "a <= fraction.to(-1) ?", a <= fraction.to(-1) )
print( "a >= fraction.to(-1) ?", a >= fraction.to(-1) )
printFraction( "fraction.parseApart { 1, 2, 3 } = ", fraction.parseApart { 1, 2, 3 } )
printFraction( "fraction.parseApart { -1, 2, 3 } = ", fraction.parseApart { -1, 2, 3 } )
printFraction( "fraction.parseApart\"1+2/3\" = ", fraction.parseApart { -1, -2, 3 } )
printFraction( "fraction.parseApart\"1+2/3\" = ", fraction.parseApart"1+2/3" )
printFraction( "fraction.parseApart\"1+2/3\" = ", fraction.parseApart"1+2/3" )
printFraction( "fraction.parseApart\"-1  2/3\" = ", fraction.parseApart"-1  2/3" )
printFraction( "fraction.parseApart\"-1  -2/3\" = ", fraction.parseApart"-1  -2/3" )
printFraction( "fraction.parseApart\"-1 + -2/3\" = ", fraction.parseApart"-1 + -2/3" )
printFraction( "fraction.parseApart\"-1 + 2/3\" = ", fraction.parseApart"-1 + 2/3" )
printFraction( "fraction.parseApart\"-1 + +2/3\" = ", fraction.parseApart"-1 + +2/3" )
printFraction( "fraction.parseApart\"-1 +2/3\" = ", fraction.parseApart"-1 +2/3" )

--[[
Execute Result:
a = (6/9)
Simplified, a = (2/3)
b = (4/5)
Simplified, b = (4/5)
c = (-2/5)
-c = (2/5)
5 - c = (27/5)
5 + c - 2 = (13/5)
3*c = (-6/5)
2/c = -5
(19/10)
(19/10)
(19/10)
(1/2)
a^2 = (4/9)
1/a = (3/2)
1/a^2 = (9/4)
a = (2/3)
b = (4/5)
b/a = (6/5)
b/a^2 = (9/5)
fraction.toApart(b/a^2) = (1+4/5)
fraction.toDecimal(b/a^2) = 1.8
-b/a^2 = (-9/5)
fraction.toApart(-b/a^2) = (-3+1/5)
fraction.toDecimal(-b/a^2) = -1.8
Changed, a = (12/6)
a[1] = 12
a[2] = 6
a == b ?        false
a ~= b ?        true
a == fraction"2" ?      true
a ~= fraction"2" ?      false
not (a == fraction"2") ?        false
a < b ? false
a < fraction"2" ?       false
fraction"2" > a ?       false
a > fraction"2" ?       false
a > b ? true
a <= b ?        false
a >= b ?        true
a <= fraction"2" ?      true
a >= fraction"2" ?      true
a <= fraction.to(2) ?   true
a >= fraction.to(2) ?   true
a <= fraction.to(-1) ?  false
a >= fraction.to(-1) ?  true
fraction.parseApart { 1, 2, 3 } = (5/3)
fraction.parseApart { -1, 2, 3 } = (-1/3)
fraction.parseApart"1+2/3" = (-5/3)
fraction.parseApart"1+2/3" = (5/3)
fraction.parseApart"1+2/3" = (5/3)
fraction.parseApart"-1  2/3" = (-1/3)
fraction.parseApart"-1  -2/3" = (-5/3)
fraction.parseApart"-1 + -2/3" = (-5/3)
fraction.parseApart"-1 + 2/3" = (-1/3)
fraction.parseApart"-1 + +2/3" = (-1/3)
fraction.parseApart"-1 +2/3" = (-1/3)
--]]





 

Posted by Scripter
,