*  html 문서에서 meq 태그를 이용한 수학식 표현

 참고  1) m 태그 내의 수식 입력은 tex 수식 입력과는 많이 다릅니다.
         2) TeX 모르는 초, 중, 고 과정에 적합합니다.
         3) 서버에 TeX 시스템이 설치되어 있지 않아도 됩니다. 
             PhpMathPublisher 만 설치되어 있어도 됩니다.
         4) m 태그 내의 수식 입력 양식을 참고하십시오.
         5) PhpMathPublisher 와 달리 html 문서 내에 작성된 m 태그를
             온라인 상에 직접 img 태그로 변환하여 보여줍니다.
         (* 현재 Chrome에서는 동작하지 않습니다.)
         (* IE8 에서는 되는 것도 있고 안되는 것도 잇네요.)


추가:
    가만히 생각해 보니 m 태그를 사용하다 보면
            부등식  "4 < m .... m > 7" 을 m 태그로 둘러쌀 때 문제가 생길 수 있겠습니다.
    그러므로, m 태그보다는 meq 태그를 추천합니다. meq 는 Mathematical EQuation 의
    줄임글입니다. meq 태그 속의 내용이 size{숫자} 로 시작되면 그 숫자 만큼의 size
    속성이 출력물에 반영됩니다.

예 1: (img 태그를 사용한 경우)
<img src="http://www.mathkotex.com/mathpublisher/matheq.php? size{36} log_2 1024" />
라고 입력하면

가 됩니다. (IE8에서는 수식이 안 보이지만, IE9, FF, Chrome, Sapari 에서는 수식이 보입니다.)


예 2: (meq 태그를 적용한 경우)
<meq> size{64}  x/{1 + x} </meq>
라고 입력하면
size{64} x/{1 + x}
가 됩니다. (이것도 역시 IE8에서는 수식이 안 보이지만, IE9, FF, Chrome, Sapari 에서는 수식이 보입니다.)


* tistory 블로그에서 meq 태그의 수학식을 사용할려면,
  관리자 모드의 [HTML/CSS 편집] 모드로 가서 skin.html 편집에서 head 영역의 javascript 부분에 한 줄
<script type="text/javascript" src="http://www.mathkotex.com/mathpublisher/meqtag.js"></script>
을 하고, skin.html 이 아 주 끝 </body></html> 직전에
<!--[if lt  IE 9]>
<script type="text/javascript">
        phpeqn.init();
</script>
<![endif]-->
를 추가합니다. 그러면 tistory 블록그에서도 meq 태그를 쓸 수 있습니다. 
(IE8은 아직 안되네요....)
http://www.mathkotex.com/mathpublisher/ 로 가시면 meq 태그 관련 자료를 더 보실 수 있습니다,.



 관련 자료 : PhpMathPublisher 
      사용법: 퍼블리셔라는 이름에서 시사하듯이
                 php 애플리케이션을 실행하면 
                 m 태그 적용 html 문서(또는 그 일부)가 img 태그 적용 문서로 변환된다.
                 이  변환된 문서를 웹에 게시하한다.

관련 자료 2: WordPress 에서 PhpMathPublisher 를 사용하기
          1) Plugin created by Ron Fredericks : http://wordpress.org/extend/plugins/wpmathpub/
          2) Plugin created by Timm Severin : http://wordpress.org/extend/plugins/wpmathpublisher/


Posted by Scripter
,
Posted by Scripter
,

[이차방정식의 근의 공식]

a \ne 0 이면, 2차방정식 ax^2 + bx + c = 0 의 두 근은

         x = {-b \pm \sqrt{b^2-4ac} \over 2a}

이다.

(증명)

\[ ax^2 + bx + c = 0 \] \[ \therefore x^2 + \frac{b}{a} x + \frac{c}{a} = 0 \] \[ \therefore x^2 + \frac{b}{a} x = - \frac{c}{a} \] \[ \therefore x^2 + \frac{b}{a} x + \left( \frac{b}{2a} \right)^2 = \left( \frac{b}{2a} \right)^2 - \frac{c}{a} \] \[ \therefore \left( x + \frac{b}{2a} \right)^2 = \frac{b^2}{4a^2} - \frac{4ac}{4a^2} \] \[ \therefore \left( x + \frac{b}{2a} \right)^2 = \frac{b^2- 4ac}{4a^2} \] \[ \therefore x + \frac{b}{2a} = \pm \frac{\sqrt{b^2- 4ac}}{2a} \] \[ \therefore x = - \frac{b}{2a} \pm \frac{\sqrt{b^2- 4ac}}{2a} \] \[ \therefore x = \frac{-b \pm \sqrt{b^2- 4ac}}{2a} \]



[참고]

a, b, c가 모두 실수라고 가정하자(단 a \neq 0). 그리고 저 근의 공식에서 제곱근 기호 속의 값 b^2 - 4ac 을 간단히 D 라고 하자. 즉, D = b^2 - 4ac 로 놓자. 그러면 저 이차방정식은

  1. D > 0 일 때, 서로 다른 두 실근을 가지고,
  2. D = 0 일 때, 중근을 가지고,
  3. D < 0 일 때, 서로 공액인 두 허근을 갖는다.

이런 이유로, D = b^2 - 4ac 를 주어진 저 이차방정식의 판별식(discriminant)이라고 한다,


Posted by Scripter
,

[참고 자료 1]  온라인 소인수분해(prime factorization)
[참고 자료 2]  소인수분해 설명
[참고 자료 2]  한국어 위키피디아에서 설명하는 소인수분해
[참고 자료 3]  영문 Wikipedia 에서 설명하는 소인수분해


* Mathematica 를 이용하여 정수의 소인수 분해, 모든 약수의 총합, 오일러 phi 함수값 구하기




* Maxima 를 이용하여 정수의 소인수 분해, 모든 약수의 총합, 오일러 phi 함수값 구하기
  (참고: Maxima 에서는 오일러 phi 함수명이 totient 로 되어 있다.)


* 위의 그림에서 짤린 아랫 부분도 보여주는 PDF 파일:








Posted by Scripter
,


프로그램 언어 배우는 과정의 한 예제로는 적당하지만, 알고리즘 면으로는 매우 비효율적인 소스를 C, C++, Java, C#, Python, Ruby, Groovy, Lua, Octave 언어 등으로 작성해 보았다.



* 모든 양의 약수를 구하고 소수인지 아닌지 판별하는 C 언어 소스

/**
 * Filename: findAllDivisorsNotGoodC_01.c
 *
 *  Purpose:
 *          Find all positive divisors of a given nonzero integer.
 *
 *  With VC++
 *      Compile: cl findAllDivisorsNotGoodC_01.c
 *      Execute: findAllDivisorsNotGoodC_01
 *
 *  With gcc
 *      Compile: gcc findAllDivisorsNotGoodC_01.c -o findAllDivisorsNotGoodC_01
 *      Execute: ./findAllDivisorsNotGoodC_01
 *
 *  Date: 2011. 11. 1 (Tue)
 */

#include <stdio.h>
#include <math.h>

void printUsage(const char cmd[]) {
 printf("Usage: %s [nnn]\n", cmd);
 printf("nnn should be a positive integer.\n");
}

int main(int argc, char *argv[]) {
 int n;
 int cnt = 0;
 long sum = 0;
 int i;
 if (argc == 2) {
  n = atoi(argv[1]);
  printf("The input number is %d.\n", n);
  if (n > 0) {
   if (n <= 0x3FFFFFFF) {
    printf("The positive divisors of %d are ", n);
    for (i = 1; i <= n; i++) {
     if (n % i == 0) {
      printf("%d", i);
      cnt++;
      sum += i;
      if (i < n) {
       printf(", ");
      }
     }
    }
    printf(".\n");
    printf("The sum of all positive divisors of %d is %ld.\n", n, sum);
    printf("The number of positive divisors of %d is %d.\n", n, cnt);
    if (cnt == 2) {
     printf("Hence the positive integer %d is a prime number.\n", n);
    }
    else {
     printf("Hence the positive integer %d is not a prime number.\n", n);
    }
   }
   else {
    printf("It is too big.\n");
    printf("The input integer shoud be in the range from 1 to %d.\n", 0x3FFFFFFF);
   }
  }
  else {
   printf("It is not positive.\n");
  }
 }
 else {
  printUsage(argv[0]);
 }
    return 0;
}




* 모든 양의 약수를 구하고 소수인지 아닌지 판별하는 C++ 언어 소스

/**
 * Filename: findAllDivisorsNotGoodCPP_01.cpp
 *
 *  Purpose:
 *          Find all positive divisors of a given nonzero integer.
 *
 *  With VC++
 *      Compile: cl findAllDivisorsNotGoodCPP_01.cpp /EHsc
 *      Execute: findAllDivisorsNotGoodCPP_01
 *
 *  With g++
 *      Compile: g++ findAllDivisorsNotGoodCPP_01.cpp -o findAllDivisorsNotGoodCPP_01
 *      Execute: ./findAllDivisorsNotGoodCPP_01
 *
 *  Date: 2011. 11. 1 (Tue)
 */

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

using namespace std;

void printUsage(const char cmd[]) {
 cout << "Usage: " << cmd << " [nnn]" << endl;
 cout << "nnn should be a positive integer." << endl;
}

int main(int argc, char *argv[]) {
 int n;
 int cnt = 0;
 long sum = 0;
 int i;
 if (argc == 2) {
  n = atoi(argv[1]);
  cout << "The input number is " << n << "." << endl;
  if (n > 0) {
   if (n <= 0x3FFFFFFF) {
    cout << "The positive divisors of " << n << " are ";
    for (i = 1; i <= n; i++) {
     if (n % i == 0) {
      cout << i;
      cnt++;
      sum += i;
      if (i < n) {
       cout << ", ";
      }
     }
    }
    cout << "." << endl;
    cout << "The sum of all positive divisors of " << n << " is " << sum << "." << endl;
    cout << "The number of positive divisors of " << n << " is " << cnt << "." << endl;
    if (cnt == 2) {
     cout << "Hence the positive integer " << n << " is a prime number." << endl;
    }
    else {
     cout << "Hence the positive integer " << n << " is not a prime number." << endl;
    }
   }
   else {
    cout << "It is too big." << endl;
    cout << "The input integer shoud be in the range from 1 to " << 0x3FFFFFFF << "." << endl;
   }
  }
  else {
   cout << "It is not positive." << endl;
  }
 }
 else {
  printUsage(argv[0]);
 }
    return 0;
}




* 모든 양의 약수를 구하고 소수인지 아닌지 판별하는 C# 언어 소스

/**
 * Filename: FindAllDivisorsNotGoodCS_01.cs
 *
 *    Purpose:
 *          Find all positive divisors of a given nonzero integer.
 *
 *  Compile: csc FindAllDivisorsNotGoodCS_01.cs
 *  Execute: FindAllDivisorsNotGoodCS_01
 *
 *  Date: 2011. 11. 1 (Tue)
 */

using System;

public class FindAllDivisorsNotGoodCS_01 {

 static void PrintUsage(string cmd) {
  Console.WriteLine("Usage: " + cmd + " [nnn]");
  Console.WriteLine("nnn should be a positive integer.");
 }

 public static void Main(string[] args) {
  int n;
  int cnt = 0;
  long sum = 0;
  if (args.Length == 1) {
   try {
    n = Convert.ToInt32(args[0]);
    Console.WriteLine("The input number is " + n + ".");
    if (n > 0) {
     if (n <= 0x3FFFFFFF) {
      Console.Write("The positive divisors of " + n + " are ");
      for (int i = 1; i <= n; i++) {
       if (n % i == 0) {
        Console.Write("" + i);
        cnt++;
        sum += i;
        if (i < n) {
         Console.Write(", ");
        }
       }
      }
      Console.WriteLine(".");
      Console.WriteLine("The sum of all positive divisors of " + n + " is " + sum + ".");
      Console.WriteLine("The number of positive divisors of " + n + " is " + cnt + ".");
      if (cnt == 2) {
       Console.WriteLine("Hence the positive integer " + n + " is a prime number.");
      }
      else {
       Console.WriteLine("Hence the positive integer " + n + " is not a prime number.");
      }
     }
     else {
      Console.WriteLine("It is too big.");
      Console.WriteLine("The input integer shoud be in the range from 1 to " + 0x3FFFFFFF + ".");
     }
    }
    else {
     Console.WriteLine("It is not positive.");
    }
   }
   catch (FormatException ex) {
    Console.WriteLine(ex.Message + "\nTry agin with other number.");
    Console.WriteLine("The input integer shoud be in the range from 1 to " + 0x3FFFFFFF + ".");
    PrintUsage("FindAllDivisorsNotGoodCS_01");
   }
   catch (OverflowException ex) {
    Console.WriteLine(ex.Message + "\nTry agin with other number.");
    Console.WriteLine("The input integer shoud be in the range from 1 to " + 0x3FFFFFFF + ".");
    PrintUsage("FindAllDivisorsNotGoodCS_01");
   }
  }
  else {
   PrintUsage("FindAllDivisorsNotGoodCS_01");
  }
 }
}





* 모든 양의 약수를 구하고 소수인지 아닌지 판별하는 Java 언어 소스

/**
 * Filename: FindAllDivisorsNotGoodJava_01.java
 *
 *    Purpose:
 *          Find all positive divisors of a given nonzero integer.
 *
 *  Compile: javac FindAllDivisorsNotGoodJava_01.java
 *  Execute: java FindAllDivisorsNotGoodJava_01
 *
 *  Date: 2011. 11. 1 (Tue)
 */

public class FindAllDivisorsNotGoodJava_01 {

 static void printUsage(String cmd) {
  System.out.println("Usage: java " + cmd + " [nnn]");
  System.out.println("nnn should be a positive integer.");
 }

 public static void main(String[] args) {
  int n;
  int cnt = 0;
  long sum = 0;
  if (args.length == 1) {
   try {
    n = Integer.parseInt(args[0]);
    System.out.println("The input number is " + n + ".");
    if (n > 0) {
     if (n <= 0x3FFFFFFF) {
      System.out.print("The positive divisors of " + n + " are ");
      for (int i = 1; i <= n; i++) {
       if (n % i == 0) {
        System.out.print("" + i);
        cnt++;
        sum += i;
        if (i < n) {
         System.out.print(", ");
        }
       }
      }
      System.out.println(".");
      System.out.println("The sum of all positive divisors of " + n + " is " + sum + ".");
      System.out.println("The number of positive divisors of " + n + " is " + cnt + ".");
      if (cnt == 2) {
       System.out.println("Hence the positive integer " + n + " is a prime number.");
      }
      else {
       System.out.println("Hence the positive integer " + n + " is not a prime number.");
      }
     }
     else {
      System.out.println("It is too big.");
      System.out.println("The input integer shoud be in the range from 1 to " + 0x3FFFFFFF + ".");
     }
    }
    else {
     System.out.println("It is not positive.");
    }
   }
   catch (java.lang.NumberFormatException ex) {
    System.out.println(ex.getMessage() + " is not valid for input integers.\nTry agin with other number.");
    System.out.println("The input integer shoud be in the range from 1 to " + 0x3FFFFFFF + ".");
    printUsage("FindAllDivisorsNotGoodJava_01");
   }
  }
  else {
   printUsage("FindAllDivisorsNotGoodJava_01");
  }
 }
}



* 모든 양의 약수를 구하고 소수인지 아닌지 판별하는 Groovy 언어 소스

/**
 * Filename: findAllDivisorsNotGoodGroovy_01.groovy
 *
 *    Purpose:
 *          Find all positive divisors of a given nonzero integer.
 *
 *  Execute: groovy findAllDivisorsNotGoodGroovy_01.groovy 111141111
 *
 *  Compiling only: groovyc findAllDivisorsNotGoodGroovy_01.groovy
 *  Execute after compile: java -cp .;%GROOVY_HOME%\embeddable\groovy-all-1.8.2.jar findAllDivisorsNotGoodGroovy_01 111141111
 *
 *  Date: 2011. 11. 1 (Tue)
 */

def printUsage(cmd) {
 println("Usage: groovy " + cmd + " [nnn]")
 println("nnn should be a positive integer.")
}

def n
def cnt = 0
def sum = 0
if (args.length == 1) {
 try {
  n = args[0] as int;
  println("The input number is " + n + ".")
  if (n > 0) {
   if (n <= 0x3FFFFFFF) {
    print("The positive divisors of " + n + " are ")
    for (int i = 1; i <= n; i++) {
     if (n % i == 0) {
      print("" + i)
      cnt++
      sum += i
      if (i < n) {
       print(", ")
      }
     }
    }
    println(".")
    println("The sum of all positive divisors of " + n + " is " + sum + ".")
    println("The number of positive divisors of " + n + " is " + cnt + ".")
    if (cnt == 2) {
     println("Hence the positive integer " + n + " is a prime number.")
    }
    else {
     println("Hence the positive integer " + n + " is not a prime number.")
    }
   }
   else {
    println("It is too big.")
    println("The input integer shoud be in the range from 1 to " + 0x3FFFFFFF + ".")
   }
  }
  else {
   println("It is not positive.")
  }
 }
 catch (java.lang.NumberFormatException ex) {
  println(ex.getMessage() + " is not valid for input integers.\nTry agin with other number.")
  println("The input integer shoud be in the range from 1 to " + 0x3FFFFFFF + ".")
  printUsage("findAllDivisorsNotGoodGroovy_01.groovy")
 }
}
else {
 printUsage("findAllDivisorsNotGoodGroovy_01.groovy")
}



* 모든 양의 약수를 구하고 소수인지 아닌지 판별하는 Python 언어 소스

# Filename: findAllDivisorsNotGoodPython_01.py
#
#    Purpose:
#          Find all positive divisors of a given nonzero integer.
#
#  Execute: python findAllDivisorsNotGoodPython_01.py [nnn]
#
#  Date: 2011. 11. 1 (Tue)

import sys

def printUsage(cmd):
 print "Usage: python %s [nnn]" % cmd
 print "nnn should be a positive integer."

n = 0
cnt = 0
sum = 0

if len(sys.argv) == 2:
 try:
  pass
  n = int(sys.argv[1])
  print "The input number is %d." % n
  if n > 0:
   if n <= 0x3FFFFFFF:
    sys.stdout.write( "The positive divisors of %d are " % n )
    for i in range(1,  n + 1):
     if n % i == 0:
      sys.stdout.write("%d" % i)
      cnt += 1
      sum += i
      if i < n:
       sys.stdout.write(", ")
    print "."
    print "The sum of all positive divisors of %s is %s." % (n, sum)
    print "The number of positive divisors of %s is %s." % (n, cnt)
    if cnt == 2:
     print "Hence the positive integer %s is a prime number." % n
    else:
     print "Hence the positive integer %s is not a prime number." % n
   else:
    print "It is too big."
    print "The input integer shoud be in the range from 1 to %d." % 0x3FFFFFFF
  else:
   print "It is not positive."
 except ValueError, ex:
  print "%s.\nThe input string cannot be parsed as an integer.\nTry agin with other number." % ex
  print "The input integer shoud be in the range from 1 to %d." % 0x3FFFFFFF
  printUsage(sys.argv[0])
else:
 printUsage(sys.argv[0])




* 모든 양의 약수를 구하고 소수인지 아닌지 판별하는 Ruby 언어 소스

# Filename: findAllDivisorsNotGoodRuby_01.rb
#
#    Purpose:
#          Find all positive divisors of a given nonzero integer.
#
#  Execute: ruby findAllDivisorsNotGoodRuby_01.rb [nnn]
#
#
#  Date: 2011. 11. 1 (Tue)

def printUsage(cmd)
 print "Usage: ruby %s [nnn]\n" % cmd
 print "nnn should be a positive integer.\n"
end

n = 0
cnt = 0
sum = 0

if ARGV.length == 1
 begin
  n = ARGV[0].to_i
  print "The input number is %s.\n" % n
  if n > 0
   if n <= 0x3FFFFFFF
    print "The positive divisors of %d are " % n
    for i in 1..n do
     if n % i == 0
      print "%d" % i
      cnt += 1
      sum += i
      if i < n
       print ", "
      end
     end
    end
    print ".\n"
    print "The sum of all positive divisors of %s is %s.\n" % [n, sum]
    print "The number of positive divisors of %s is %s.\n" % [n, cnt]
    if cnt == 2
     print "Hence the positive integer %d is a prime number.\n" % n
    else
     print "Hence the positive integer %d is not a prime number.\n" % n
    end
   else
    print "It is too big.\n"
    print "The input integer shoud be in the range from 1 to %s\n." % 0x3FFFFFFF
   end
  else
   print "It is not positive.\n"
  end
 rescue SyntaxError, NameError => boom
  print "%s.\n" % boom
  print "The input string is not valid as an integer.\nTry agin with other number.\n" % boom
  print "The input integer shoud be in the range from 1 to %d.\n" % 0x3FFFFFFF
  printUsage("findAllDivisorsNotGoodGroovy_01.groovy")
 end
else
 printUsage("findAllDivisorsNotGoodRuby_01.rb")
end







* 모든 양의 약수를 구하고 소수인지 아닌지 판별하는 Lua 언어 소스

-- Filename: findAllDivisorsNotGoodLua_01.lua
--
--    Purpose:
--          Find all positive divisors of a given nonzero integer.
--
--  Execute: lua findAllDivisorsNotGoodLua_01.lua [nnn]
--
--
--  Date: 2011. 11. 1 (Tue)

function printUsage(cmd)
 print( "Usage: lua " .. cmd .. " [nnn]" )
 print "nnn should be a positive integer."
end

n = 0
cnt = 0
sum = 0

if #arg == 1 then
 if not tonumber(arg[1]) then
  print("Eception in parsing " .. arg[1] .. ".")
  print "Try agin with other number."
  print( "The input integer shoud be in the range from 1 to " .. 0x3FFFFFFF .. "." )
  printUsage(arg[0])
 else
  n = tonumber(arg[1])
  print( "The input number is " .. n .. "." )
  if n > 0 then
   if n <= 0x3FFFFFFF then
    io.write("The positive divisors of " .. n .. " are ")
    for i = 1,n do
     if n % i == 0 then
      io.write( "" .. i )
      cnt = cnt + 1
      sum = sum + i
      if i < n then
       io.write( ", " )
      end
     end
    end
    print ""
    print( "The sum of all positive divisors of " .. n .. " is " .. sum .. "." )
    print( "The number of positive divisors of " .. n .. " is " .. cnt .. "." )
    if cnt == 2 then
     print( "Hence the positive integer " .. n  .. " is a prime number." )
    else
     print( "Hence the positive integer " .. n  .. " is not a prime number." )
    end
   else
    print "It is too big."
    print( "The input integer shoud be in the range from 1 to " .. 0x3FFFFFFF .. "." )
   end
  else
   print "It is not positive.\n"
  end
 end
else
 printUsage(arg[0])
end




 

Posted by Scripter
,

웹에서 행렬 계산을 해주는

     온라인 행렬 계산기

* 위의 하이퍼 링크를 따라가면
  행렬식, 역행렬, 트레이스, 위수(rank), 가우스 소거법, 가우스-조르단 소거법, 고유값과 고유벡터, LU 분해, QR 분해, SVD 분해, Cholesky 분해 등의 계산 결과를 볼 수 있다.

* 행렬의 요소를 입력할 때 행의 구분자로 '캐리지 리턴'(즉, 엔터 키)와 '세미콜론'을 사용한다.
   예:    1 2 3; 4 5 6; 2 1 1
         을 입력하면 3x3 행렬로 인식하여 계산한다.


Posted by Scripter
,

무리방정식에는 무연근이 있을 수 있다.
여기서는 무리방정식

              sqrt(x + 1) = x - 2

의 풀이를 Mactimatica, Maxima 등에서는 어떻게 하는지 알아 본다.

우선 손계산으로 풀어보자.
무리방정시에는 무연근(계산 상으로는 근으로 나오지만 원래 방정식의 의마에는 맞지 얺는 근)이 나올 수 있다. 먼저 근이 존재할 범위를 알아 본다. 제곱근 기호 속이 0 이상이라야 하므로 x + 1 >= 0 즉 x >= -1 이다. 또 제곱근의 값 자체가 0 이상이므로 주어진 방정식의 우변도 0 이상이라야 한다. 그러므로 x - 2 >= 0 즉, x >= 2 이다. 그러므로 근의 존재 범위는 x >= -1 과 x >= 2 의 공통범위 x >= 2 이다. 이 범위에 있지 않는 근은 모두 무연근이므로 버린다.

이제 주어진 방정식의 양변을 제곱하면
              x + 1 = (x - 2)^2
        즉,  x + 1 = x^2 - 4x + 4
이것은 단순한 이차방정식이므로 내림차 순으로 잘 정리하여 근의 공식을 써서 풀면 된다.
             x^2 - 5x + 3 = 0
따라서    x = (5 ± sqrt(13))/2    이다.
이 중에 (5 -sqrt(13))/2 는 2 보다 작으므로 (근의 존재 범위에 맞지 않는) 무연근이라서 버린다.
그러므로 주어진 무리방정식의 해는  x = (5 + sqrt(13))/2  뿐이다.


* Mathematica 를 이용한 무리방정식의 풀이
  (Solve 는 심볼 계산으로 해를 구해주고, NSolve 는 수치적 계산으로 해를 구래준다.)




* Maxima 를 이용한 무리방정식의 풀이
  (Maxima 로는 무리반정식의 해를 심볼로 구하는 방법이 없다.
   그대신 find_root 를 사용하면 수치적 해를 구해준다.
   solve 를 써서 다항방정시의 해를 구한 다음 무연근을 버리는 방법으로 그 해를 구하였다.
   numer 는 심볼 값을 수치적 값으로 계산해 주는 명령이다. *)




* Python 에서 sympy 를 이용한 방정식의 풀이
  (* 아래에서 진한 부분만 입력하면 된다. 
      sympy 로도 무리방정식을 풀지 못해 이차반정식으로 고쳐서 풀었다. *)
>>> from sympy import *
>>> x = symbols('x')
>>> y = solve((x + 1) - (x - 2)**2, x)
>>> y
[-13**(1/2)/2 + 5/2, 13**(1/2)/2 + 5/2]
>>> y[0] >= 2
False
>>> y[1] >= 2
True
>>> y[1]
13**(1/2)/2 + 5/2
>>> N(y[1])
4.30277563773199




* Python 에서 scipy 를 이용하여 무리방정식의 수치적 해 구하기
  (* numpy 와 scipy 는 수치적 계산을 위한 파이썬 전용 라이브러리이다. *)

>>> from scipy import *
>>> from scipy.optimize import fsolve
>>> dir(fsolve)

>>> help (fsolve)

>>> def f(x): return sqrt(x + 1) - x + 2
...
>>> fsolve(f, 0)
array([ 4.30277564])
>>> fsolve(f, 9)
array([ 4.30277564])

또는

>>> from scipy import sqrt
>>> from scipy.optimize import fsolve
>>> fsolve(lambda x: sqrt(x + 1) - x + 2, 1)
array([ 4.30277564])
>>> sol = fsolve(lambda x: sqrt(x + 1) - x + 2, 1)
>>> sol
array([ 4.30277564])
>>> sol[0]
4.3027756377319948



* Octave 로 풀어보는 무리방정식
  (* Octave 로는 수치적 해를 구할 수 있다. fsolve 는 실수 범위내의 수치적 연산으로
     해를 구하고, fzero 는 복수수 범위 까지의 수치적 연산으로 해를 구해준다. 
     optimset 은 오차의 범위를 조절하기 위해 사용된다. 함수 f 의 구현에는 함수 f2 의
     구현과 달리 수식 부분 y = sqrt(x + 1) - x + 2 의 끝에 세미콜론이 없으므로 이 함수 f 가
     호출될 때 마다 이 세미콜론이 없는 구문을 만나면 y 에 저장되는 값이 출력된다, *)

octave-3.2.4.exe:1> function y = f(x)
> y = sqrt(x + 1) - x + 2
> endfunction
octave-3.2.4.exe:2> function y = f2(x)
> y = sqrt(x + 1) - x + 2;
> endfunction
octave-3.2.4.exe:3> opt = optimset("TolX", 1e-2)
opt =
{
  TolX =  0.010000
}

octave-3.2.4.exe:4> fsolve(@f, 0, opt)
y =  3
y =  3.0000
y =  3.0000
y =  1.7321
y =  1.7320
y =  1.7321
y =  0.24529
y = -0.0053636
y = 1.1321e-004
ans =  4.3026
octave-3.2.4.exe:5> fzero(@f, 0, opt)
y =  3
y =  2.4784
y =  2.3491
y =  3
y =  1.7321
y =  2.7247
y =  2.0811
y =  3
y =  1.7321
y =  12 +  3i
y = -4.6834
y =  0.31008
y = -2.1323
y = -0.0058277
y =  0.0051326
ans =  4.2962
octave-3.2.4.exe:6> fsolve(@f2, 0, opt)
ans =  4.3026
octave-3.2.4.exe:7> fzero(@f2, 0, opt)
ans =  4.2962
octave-3.2.4.exe:8> opt = optimset("TolX", 1e-12)
opt =
{
  TolX = 1.0000e-012
}

octave-3.2.4.exe:9> fsolve(@f, 0, opt)
y =  3
y =  3.0000
y =  3.0000
y =  1.7321
y =  1.7320
y =  1.7321
y =  0.24529
y = -0.0053636
y = 1.1321e-004
y = -2.3671e-006
y = 4.9493e-008
y = -1.0348e-009
ans =  4.3028
octave-3.2.4.exe:10> fzero(@f, 0, opt)
y =  3
y =  2.4784
y =  2.3491
y =  3
y =  1.7321
y =  2.7247
y =  2.0811
y =  3
y =  1.7321
y =  12 +  3i
y = -4.6834
y =  0.31008
y = -2.1323
y = -0.0058277
y = 3.3801e-006
y = -3.3794e-006
y = 4.4409e-016
y = -1.0973e-012
ans =  4.3028
octave-3.2.4.exe:11> fsolve(@f2, 0, opt)
ans =  4.3028
octave-3.2.4.exe:12> fzero(@f2, 0, opt)
ans =  4.3028



수치적 방법으로 근의 근사값을 구하는 방법은 여러 가지가 소개되어 있다.
다음은 방정식을 그 중에 가장 많이 쓰이는 (쉬운 방법) Newton 반복법을 사용하여
여러 가지 프로그램 언어로 구현해 보았다.

* 무리방정식을 풀기 위해 C 언어로 구현한 Newton 방법

/**
 * Filename solveSimpEqC_01.c
 *
 *  Purpose:
 *          Find roots of an equation by using the Newton method.
 *
 *  With VC++
 *      Compile: cl solveSimpEqC_01.c
 *      Execute: solveSimpEqC_01
 *
 *  With g++
 *      Compile: gcc solveSimpEqC_01.c -o solveSimpEqC_01
 *      Execute: ./solveSimpEqC_01
 *
 *  Date: 2011. 10. 30 (Sun)
 */

#include <stdio.h>
#include <math.h>

double f(double x) {
 return sqrt(x + 1) - x + 2;
}

double df(double x) {
 return 1/(2*sqrt(x + 1)) - 1;
}

double newtonIter(double (*func)(double), double (*dfunc)(double), double x0, double err) {
  double x = x0;
  double x1;
  int i;
  for (i = 0; i < 100; i++) {
   x1 = x;
   x = x - func(x)/dfunc(x);
   if (abs(x - x1) < err) {
       printf("Break loop after the %d-th iteration\n", i + 1);
       break;
   }
  }
  return x;
}

int main() {
 double x = newtonIter(&f, &df, 9, 1e-8);
    printf("x = %g\n", x);
    return 0;
}

/*
Execution result after compiling with VC++:
Break loop after the 2-th iteration
x = 4.30302

Execution result after compiling with gcc:
Break loop after the 4-th iteration
x = 4.30278
*/





* 무리방정식을 풀기 위해 C++ 언어로 구현한 Newton 방법

/**
 * Filename solveSimpEqCPP_01.cpp
 *
 *  Purpose:
 *          Find roots of an equation by using the Newton method.
 *
 *  With VC++
 *      Compile: cl solveSimpEqCPP_01.cpp /EHsc
 *      Execute: solveSimpEqCPP_01
 *
 *  With g++
 *      Compile: g++ solveSimpEqCPP_01.cpp -o solveSimpEqCPP_01
 *      Execute: ./solveSimpEqCPP_01
 *
 *  Date: 2011. 10. 30 (Sun)
 */

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

using namespace std;

double f(double x) {
 return sqrt(x + 1) - x + 2;
}

double df(double x) {
 return 1/(2*sqrt(x + 1)) - 1;
}

double newtonIter(double(*func)(double), double(*dfunc)(double), double x0, double err) {
  double x = x0;
  double x1;
  for (int i = 0; i < 100; i++) {
   x1 = x;
   x = x - func(x)/dfunc(x);
   if (abs(x - x1) < err) {
       cout << "Break loop after the " << i + 1 << "-th iteration" << endl;
       break;
   }
  }
  return x;
}

int main() {
 double sol = newtonIter(&f, &df, 9, 1e-8);
    cout << "x = " <<  sol << endl;
    return 0;
}

/*
Execution Result:
Break loop after the 4-th iteration
x = 4.30278
*/






* 무리방정식을 풀기 위해 Java 언어로 구현한 Newton 방법

/**
 *  Filename SolveSimpEqJava_01.java
 *
 *  Purpose:
 *          Find roots of an equation by using the Newton method.
 *
 *  Compile: javac SolveSimpEqJava_01.java
 *  Execute: java SolveSimpEqJava_01
 *
 *  Date: 2011. 10. 30 (Sun)
 */

import java.lang.*;

public class SolveSimpEqJava_01 {

 private static double f(double x) {
  return Math.sqrt(x + 1) - x + 2;
 }

 private static double df(double x) {
  return 1/(2*Math.sqrt(x + 1)) - 1;
 }

 private static double newtonIter(double x0, double err) {
  double x = x0;
  double x1;
  for (int i = 0; i < 100; i++) {
   x1 = x;
   x = x - f(x)/df(x);
   if (Math.abs(x - x1) < err) {
        System.out.printf("Break loop after the %d-th iteration\n", i + 1);
    break;
   }
   }
  return x;
 }

 public static void main(String[] args) {
  double sol = newtonIter(9, 1e-8);
  System.out.printf("x = %g\n", sol);
 }
}

/*
Execution Result:
Break loop after the 4-th iteration
x = 4.30278
*/







* 무리방정식을 풀기 위해 Groovy 언어로 구현한 Newton 방법
   (소스 내용은 Java 의 것과 같으나 파일 확장명만 groovy 로 바꾼 것)

/**
 *  Filename solveSimpEqGroovy_01.groovy
 *
 *  Purpose:
 *          Find roots of an equation by using the Newton method.
 *
 *  Execute: groovy solveSimpEqGroovy_01.groovy
 *
 *  Date: 2011. 10. 30 (Sun)
 */

import java.lang.*;

public class SolveSimpEqJava_01 {

 private static double f(double x) {
  return Math.sqrt(x + 1) - x + 2;
 }

 private static double df(double x) {
  return 1/(2*Math.sqrt(x + 1)) - 1;
 }

 private static double newtonIter(double x0, double err) {
  double x = x0;
  double x1;
  for (int i = 0; i < 100; i++) {
   x1 = x;
   x = x - f(x)/df(x);
   if (Math.abs(x - x1) < err) {
         System.out.printf("Break loop after the %d-th iteration\n", i + 1);
    break;
   }
   }
  return x;
 }

 public static void main(String[] args) {
  double sol = newtonIter(9, 1e-8);
  System.out.printf("x = %g\n", sol);
 }
}

/*
Execution Result:
Break loop after the 4-th iteration
x = 4.30278
*/






* 무리방정식을 풀기 위해 Groovy 언어로 구현한 Newton 방법
  (Groovy 언어의 특징을 살려 아주 간단하게 고친 것)

/**
 *  Filename solveSimpEq_01.groovy
 *
 *  Purpose:
 *          Find roots of an equation by using the Newton method.
 *
 *  Execute: groovy solveSimpEq_01.groovy
 *
 *  Date: 2011. 10. 30 (Sun)
 */

def f(x) {
 return Math.sqrt(x + 1) - x + 2
}

def df(x) {
 return 1/(2*Math.sqrt(x + 1)) - 1
}

def newtonIter(x0, err) {
 def x = x0
 def x1
 for (int i = 0; i < 100; i++) {
  x1 = x
  x = x - f(x)/df(x)
      if (Math.abs(x - x1) < err) {
           println("Break loop after the " + (i + 1) + "-th iteration")
           break
      }
  }
  return x
}

sol = newtonIter(9, 1e-8)
println("x = " +  sol)

/*
Execution Result:
Break loop after the 4-th iteration
x = 4.302775637731995
*/





* 무리방정식을 풀기 위해 Python 언어로 구현한 Newton 방법

#!/env/python
#
#  Filename solveSimpEq_01.py
#
#  Purpose:
#          Find roots of an equation by using the Newton method.
#
#  Execute: python solveSimpEq_01.py
#
#  Date: 2011. 10. 30 (Sun)

import math

def f(x):
 return math.sqrt(x + 1) - x + 2

def df(x):
 return 1/(2*math.sqrt(x + 1)) - 1

def newtonIter(x0, err):
 x = x0
 for i in range(0, 100):
   x1 = x
   x = x - f(x)/df(x)
   if abs(x - x1) < err:
       print "Break loop after the %d-th iteration" % (i + 1)
       break
 return x

sol = newtonIter(9, 1e-8)
print "x = %g" % sol

"""
Break loop after the 4-th iteration
x = 4.30278
"""





* 무리방정식을 풀기 위해 Ruby 언어로 구현한 Newton 방법

#!/env/ruby
#
#  Filename solveSimpEq_01.rb
#
#  Purpose:
#          Find roots of an equation by using the Newton method.
#
#  Execute: ruby solveSimpEq_01.rb
#
#  Date: 2011. 10. 30 (Sun)

def f(x)
 return Math::sqrt(x + 1) - x + 2
end

def df(x)
 return 1/(2*Math::sqrt(x + 1)) - 1
end

def newtonIter(x0, err)
 x = x0
 for i in 0..100 do
   x1 = x
   x = x - f(x)/df(x)
   if (x - x1).abs < err
       print "Break loop after the %d-th iteration\n" % (i + 1)
       break
      end
     end
 return x
end

sol = newtonIter(9, 1e-8)
print "x = %g\n" % sol

=begin
Execution Result:
Break loop after the 4-th iteration
x = 4.30278
=end





* 무리방정식을 풀기 위해 Lua 언어로 구현한 Newton 방법

--[[
  Filename solveSimpEq_01.lua

  Purpose:
          Find roots of an equation by using the Newton method.

  Execute: lua solveSimpEq_01.lua

  Date: 2011. 10. 30 (Sun)
]]--

function f(x)
 return math.sqrt(x + 1) - x + 2
end

function df(x)
 return 1/(2*math.sqrt(x + 1)) - 1
end

function newtonIter(x0, err)
 x = x0
 for i = 1,100 do
   x1 = x
   x = x - f(x)/df(x)
   if math.abs(x - x1) < err then
       print( "Break loop after the " .. (i + 1) .. "-th iteration" )
       break
      end
     end
 return x
end

sol = newtonIter(9, 1e-8)
print( "x = " .. sol )

--[[
Execution Result:
Break loop after the 5-th iteration
x = 4.302775637732
]]--






 

Posted by Scripter
,

 

C 언어, Java 언어, Python 언어 등으로 프로그래밍할 때 부동소수점수(floating point number) 를 많이 사용한다. 보동 double 타입이라고 부르는 수치형 데이터인데, 이 데이터의 처리 가능 범위는
대략


      (   -1.79769313486231E308    ~    1.79769313486232E308  )



 

정밀도   비트수 범위   유효숫자 개수(10진수)
단정밀도      32 bits      ±1.18×10−38 to ±3.4×1038            약 7개
배정밀도      64 bits      ±2.23×10–308 to ±1.80×10308           약 15개


이다.

  그렇다면 1.0E-190 에 해당하는 부동소수점수는 0 이 아니며  이것의 제곱 1.0E-380 도 0이 아니다. 그런데 1.0E-380 을 컴퓨터 계산에서는 어떻게 처리될까? 아마도 0 이라고 하거나, 아주 엉뚱한 값이라고 할 수도 있다. 이와 같이 0 이 아닌 수의 제곱이나 세제곱이 컴퓨터 계산으로는 엉뚱한 값이  될 수 있음을 염두에 두어야 한다. 0은 아니지만 아주 작은 두 수의 곱의 경우에도 이런 현상(언더플로우)을 초래할 수 있다.

  이제 직각삼각형의 빗변의 길이를 구하는 문제를 생가해 보자.
직각을 낀 두 변의 길이가 1 인 직각이등변삼각형의 빗변의 길이는 얼마일까?
당연히 그 답은 sqrt(2) = 1.4142.... 이다,
그러면 직각을 낀 두 변의 길이가 1.0E-190 인 직각이등변삼각형의 빗변의 길이는 얼마일까?
이 때도 당연히 그 답은 sqrt(2)*1.0E-190 = 1.4142....E-190 이다,
컴퓨터 계산 상으로도 그렇게 나올까?
a = 1.0E-190 로 놓고,

        빗변의 길이 = sqrt(a*a + a*a)
                         = sqrt(1.0E-380 + 1.0E-380)
                         = sqrt(0 + 0)   (또는 엉뚱한 값)
                         = 0   (또는 엉뚱한 값)

단순히 수학 시간에 배운대로 피타고리스 정리를 쓰면 위의 계산 처럼 기대하지 않은 엉뚱한 값이 될 수 있다. 그 빗변의 길이 1.4142....E-190 는 배정밀도 부동소수점수로 처리 가능하므로 이런 언더플로우(underflow) 문제를 해결하여야 한다,  두변의 길이가 매우 큰 경우에는 오버플로우가 발생한다, 그래서 직각삼각형의 빗변의 길이를 언도플로우나 오버플로우를 방지하는 다음 알고리즘이 필요하다.

pythagAlgorithm          ; 언더플로우와 오버플로우를 방지
    Input a, b     ; 직각을 낀 두 변의 길이
    a1 <- abs(a)
    b1 <- abs(b)
    if a1 >b1:
        Output a1*sqrt(1.0 + (b1/a1)*(b1/a1))
    else:
if b1 == 0.0:
       Output 0.0
 else:
        Output b1*sqrt(1.0 + (a1/b1)*(a1/b1))  



* 불완전한 C 언어 구현
  (Stabe, c = ...  부분의 출력이 정확하지 못하다. gcc 와 Visual C++ 의 결과가 다르다. )

#include <stdio.h>
#include <math.h>
  
double pythag(double a, double b) {
    double absa = abs(a);
    double absb = abs(b);
    if (absa > absb) {
         return absa*sqrt(1.0 + (absb/absa)*(absb/absa));
    }
    else {
        if (absb == 0.0) {
            return 0.0;
         }
         else {
             return absb*sqrt(1.0 + (absa/absb)*(absa/absb));
         }
    }
}

int main() {
    double a = 1.0E-190;
    double b = 1.0E-190;
    double c = sqrt(a*a + b*b);
    printf("a = %g\n", a);
    printf("b = %g\n", b);
    printf("Unstable, c = sqrt(a*a + b*b) = %g\n", c);
    c = pythag(a, b);
    printf("Stable, c = %g\n", c);
    printf("b*sqrt(2) = %g\n", b*sqrt(2));

    return 0;
}

/*
gcc 로 컴파일하여 실행한 결과:
-----------------------------
a = 1e-190
b = 1e-190
Unstable,  c = sqrt(a, b) = 0
Stable,  c = 1.96204e+09
b*sqrt(2) = 1.41421e-190

Visual C++ 로 컴파일하여 실행한 결과:
-----------------------------------
a = 1e-190
b = 1e-190
Unstable, c = sqrt(a*a + b*b) = 0
Stable, c = 0
b*sqrt(2) = 1.41421e-190
*/


* 수정된 C 언어 소스
  (위의 소스는 절대값을 구하는 abs 함수에 문제가 있었다.
    그래서 절대값 계산하는 ABS 매크로를 만들어 사용하였다 ).

#include <stdio.h>
#include <math.h>
 
#define ABS(x) (((x) < 0) ? (-(x)) : (x))
 
double pythag(double a, double b) {
    double absa = ABS(a);
    double absb = ABS(b);
    if (absa > absb) {
        return absa*sqrt(1.0 + (absb/absa)*(absb/absa));
    }
    else {
        if (absb == 0.0) {
            return 0.0;
        }
        else {
            return absb*sqrt(1.0 + (absa/absb)*(absa/absb));
        }
    }
}

int main() {
    double a = 1.0E-190;
    double b = 1.0E-190;
    double c = sqrt(a*a + b*b);
    printf("a = %g\n", a);
    printf("b = %g\n", b);
    printf("Unstable, c = sqrt(a*a + b*b) = %g\n", c);
    c = pythag(a, b);
    printf("Stable, c = %g\n", c);
    printf("b*sqrt(2) = %g\n", b*sqrt(2));

    return 0;
}

/*
gcc 와 Visual C++ 로 컴파일하여 실행한 결과:
--------------------------------------------
a = 1e-190
b = 1e-190
Unstable, c = sqrt(a*a + b*b) = 0
Stable, c = 1.41421e-190
b*sqrt(2) = 1.41421e-190
*/


* C++ 언어로 직각삼각형의 빗변의 길이 구하기
   ( C++ 언어에서는 위의 C 언어에서의 절대값 문제가 발생하지 않는다. )

#include <iostream>
#include <cmath>
 
using namespace std;
 
double pythag(double a, double b) {
    double absa = abs(a);
    double absb = abs(b);
    if (absa > absb) {
        return absa*sqrt(1.0 + (absb/absa)*(absb/absa));
    }
    else {
        if (absb == 0.0) {
            return 0.0;
        }
        else {
            return absb*sqrt(1.0 + (absa/absb)*(absa/absb));
        }
    }
}

int main() {
    double a = 1.0E-190;
    double b = 1.0E-190;
    double c = sqrt(a*a + b*b);
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "Unstable, c = sqrt(a*a + b*b) = " << c << endl;
    c = pythag(a, b);
    cout << "Stable, c = pythag(a, b) = " << c << endl;
    cout << "b*sqrt(2.0) = " << b*sqrt(2.0) << endl;
   
    return 0;
}

/*
g++와 Visual C++ 로 컴파일하여 실행한 결과:
--------------------------------------------
a = 1e-190
b = 1e-190
Unstable, c = sqrt(a*a + b*b) = 0
Stable, c = 1.41421e-190
b*sqrt(2) = 1.41421e-190
*/





* C# 언어로 직각삼각형의 빗변의 길이 구하기
   ( C# 언어에서는 위의 C 언어에서의 절대값 문제가 발생하지 않는다. )

// Filename: TestPythag.cs
//
//  Purpose:
//        Stable Pythagoras without underflow or overflow.
//
//  Compile: csc TestPythag.cs
//  Execute: TestPythag
//
// Date: 2011. 10. 22 (Sat)


using System;

public class TestPythag {
    public double Pythag(double a, double b) {
  double absa = Math.Abs(a);
  double absb = Math.Abs(b);
  if (absa > absb) {
   return absa*Math.Sqrt(1.0 + (absb/absa)*(absb/absa));
  }
     else {
         if (absb == 0.0) {
          return 0.0;
         }
         else {
          return absb*Math.Sqrt(1.0 + (absa/absb)*(absa/absb));
         }
        }
 }

    public static void Main(string[] args) {
        double a = 1.0E-190;
        double b = 1.0E-190;
        double c = Math.Sqrt(a*a + b*b);
        Console.WriteLine("a = {0}", a);
        Console.WriteLine("b = {0}", b);
        Console.WriteLine("Unstable, c = sqrt(a*a + b*b) = {0}", c);
       
        TestPythag app = new TestPythag();
        c = app.Pythag(a, b);
        Console.WriteLine("Stable, c = Pythag(a, b) = {0}", c);
        Console.WriteLine("b*Math.Sqrt(2) = {0}", b*Math.Sqrt(2));
    }
}

/*
실행 결과:
---------
a = 1E-190
b = 1E-190
Unstable, c = sqrt(a*a + b*b) = 0
Stable, c = Pythag(a, b) = 1.4142135623731E-190
b*Math.Sqrt(2) = 1.4142135623731E-190
*/



* Java 언어로 직각삼각형의 빗변의 길이 안정하게 계산하기.
  ( Java 언어에서도 절대값 문제는 발생하지 않는다. )

// Filename: TestPythag.java
//
//  Purpose:
//        Stable Pythagoras without underflow or overflow.
//
//  Compile: javac TestPythag.java
//  Execute: java TestPythag
//
// Date: 2011. 10. 22 (Sat)

public class TestPythag {
    public double pythag(double a, double b) {
  double absa = Math.abs(a);
  double absb = Math.abs(b);
  if (absa > absb) {
   return absa*Math.sqrt(1.0 + (absb/absa)*(absb/absa));
  }
     else {
         if (absb == 0.0) {
          return 0.0;
         }
         else {
          return absb*Math.sqrt(1.0 + (absa/absb)*(absa/absb));
         }
        }
 }

    public static void main(String[] args) {
        double a = 1.0E-190;
        double b = 1.0E-190;
        double c = Math.sqrt(a*a + b*b);
        System.out.printf("a = %g\n", a);
        System.out.printf("b = %g\n", b);
        System.out.printf("Unstable, c = sqrt(a*a + b*b) = %g\n", c);
       
        TestPythag app = new TestPythag();
        c = app.pythag(a, b);
        System.out.printf("Stable, c = pythag(a, b) = %g\n", c);
        System.out.printf("b*Math.Sqrt(2) = %g\n", b*Math.sqrt(2));
    }
}

/*
Java 6 및 Java 7 에서의 실행 결과:
----------------------------------
a = 1.00000e-190
b = 1.00000e-190
Unstable, c = sqrt(a*a + b*b) = 0.00000
Stable, c = pythag(a, b) = 1.41421e-190
b*Math.Sqrt(2) = 1.41421e-190
*/



* Python 언어로 직각삼각형의 빗변의 길이 안정하게 계산하기

# Filename: testPythag.py
#
#  Purpose:
#        Stable Pythagoras without underflow or overflow.
#
#  Execute: python testPythag.py
#
# Date: 2011. 10. 22 (Sat)

import math

def pythag(a, b):
    absa = abs(a)
    absb = abs(b)
    if absa > absb:
        return absa*math.sqrt(1.0 + (absb/absa)*(absb/absa))
    else:
        if absb == 0.0:
            return 0.0
        else:
            return absb*math.sqrt(1.0 + (absa/absb)*(absa/absb))

a = 1.0E-190
b = 1.0E-190
c = math.sqrt(a*a + b*b)
print "a = %g" % a
print "b = %g" % b
print "Unstable, c = sqrt(a*a + b*b) = %g" % c
       
c = pythag(a, b)
print "Stable, c = pythag(a, b) = %g" % c
print "b*math.sqrt(2) = %g" % (b*math.sqrt(2))

"""
Execution Result:
----------------
a = 1e-190
b = 1e-190
Unstable, c = sqrt(a*a + b*b) = 0
Stable, c = pythag(a, b) = 1.41421e-190
b*math.sqrt(2) = 1.41421e-190
"""



* Ruby 언어로 직각삼감형의 빗변의 길이 안정하게 계산하기

# Filename: testPythag.rb
#
#  Purpose:
#        Stable Pythagoras without underflow or overflow.
#
#  Execute: ruby testPythag.rb
#
# Date: 2011. 10. 22 (Sat)

def pythag(a, b)
    absa = a.abs
    absb = b.abs
    if absa > absb then
        return absa*Math.sqrt(1.0 + (absb/absa)*(absb/absa))
    else
        if absb == 0.0 then
            return 0.0
        else
            return absb*Math.sqrt(1.0 + (absa/absb)*(absa/absb))
        end
    end
end

a = 1.0E-190
b = 1.0E-190
c = Math.sqrt(a*a + b*b)
print "a = %g\n" % a
print "b = %g\n" % b
print "Unstable, c = sqrt(a*a + b*b) = %g\n" % c
       
c = pythag(a, b)
print "Stable, c = pythag(a, b) = %g\n" % c
print "b*Math.sqrt(2) = %g\n" % (b*Math.sqrt(2))

"""
Execution Result:
----------------
a = 1e-190
b = 1e-190
Unstable, c = sqrt(a*a + b*b) = 0
Stable, c = pythag(a, b) = 1.41421e-190
b*Math.sqrt(2) = 1.41421e-190
"""



* Lua 언어로 직각삼각형의 빗변의 길이 안전하게 계산하기

-- Filename: testPythag.lua
--
--  Purpose:
--        Stable Pythagoras without underflow or overflow.
--
--  Execute: lua testPythag.lua
--
-- Date: 2011. 10. 22 (Sat)

function pythag(a, b)
    absa = math.abs(a)
    absb = math.abs(b)
    if absa > absb then
        return absa*math.sqrt(1.0 + (absb/absa)*(absb/absa))
    else
        if absb == 0.0 then
            return 0.0
        else
            return absb*math.sqrt(1.0 + (absa/absb)*(absa/absb))
        end
    end
end

a = 1.0E-190
b = 1.0E-190
c = math.sqrt(a*a + b*b)
print( "a = " .. a )
print( "b = " .. b )
print( "Unstable, c = sqrt(a*a + b*b) = " .. c )
       
c = pythag(a, b)
print( "Stable, c = pythag(a, b) = " .. c )
print( "b*Math.sqrt(2) = " .. (b*math.sqrt(2)) )

--[[
Execution Result:
----------------
a = 1e-190
b = 1e-190
Unstable, c = sqrt(a*a + b*b) = 0
Stable, c = pythag(a, b) = 1.4142135623731e-190
b*Math.sqrt(2) = 1.4142135623731e-190
--]]






 

Posted by Scripter
,

여기서는 2x2 행렬

     A = [ 1, 1/2; 1/2, 1/3 ]

의 고유값과 고유벡터를 구하는 여러가지 방법을 소개한다.

정의 (고유값과 고유벡터)
주어진 m by n 행렬 A 에 대하여

   Av = λv   (단, v 는 영아닌 벡터, λ 는 스칼라)

를 만족하는 v 와 λ 가 존재할 때, v 를 A 의 고유벡터, λ 를 A 의 고유값이라고 한다.


* Mathematica를 이용하여 행렬의 고규값과 고유벡터 구하기




* Maxima 를 이용하여 행렬의 고유값과 고유벡터 구하기
** 아래에서 v1 이 고유벡터이고, lambda1 이 고유값이다.
    ( 그런데, v1 이 행벽터로 표현되어 잇다. 
      그러므로 이를 transpose 하여 열벡터로 바꾸어야 한다 .)



** v1 의 transpose 를 취하여 행렬 m 을 좌측에 곱해보기도 하고,
    또 스칼라 lambda1 을 곱해 보기도 한다.
    (그런데, 유리분수식이 간단하지 않다. 유리분수식을 간단히 하려면 어떻게 해야 할까?)



** 유리분수식을 간단하게 하지 않은채 수치적 값을 계산하면 뺄셈한 벡터의 성분이 0이 아니다.
    그러므로 먼저 Maxima 의 ratsimp 함수를 이용하여 유리분수식을 간단히 해야 한다.
    그런 다음 비교하면 고유감과 고유벡터의 정의 대로 계산한 식이 맞게 나온다. 



** m . v1 과 lambda1 * v1 이 같음을 확인하고 그 뺄셈도 계산해 보았다.
   (※ Maxima 의 ratsimp 함수를 써서 유리분수식을 먼자 간단히 하는 과정이 필수적이다. )




* Octave 를 이용하여 행렬의 고유값과 고유벡터 구하기
   ( 아래에서 진하게 된 부분만 입력하면 된다. )

octave.exe:1> A = [1, 1/2; 1/2, 1/3]
A =

   1.00000   0.50000
   0.50000   0.33333

octave.exe:2> [V, LAMBDA] = eig(A)
V =

   0.47186  -0.88167
  -0.88167  -0.47186

LAMBDA =

Diagonal Matrix

   0.065741          0
          0   1.267592

octave.exe:3> v1 = V(:, 1)
v1 =

   0.47186
  -0.88167

octave.exe:4> lambda1 = LAMBDA(1,1)
lambda1 =  0.065741
octave.exe:5> A*v1
ans =

   0.031021
  -0.057963

octave.exe:6> lambda1*v1
ans =

   0.031021
  -0.057963

octave.exe:7> A*v1 - lambda1*v1
ans =

  -2.4286e-017
  -2.0817e-017





* numpy, scipy 를 이용하여 행렬의 고유값과 고유벡터 구하기
   ( 아래에서 진하게 된 부분만 입력하면 된다. )

>>> from numpy import *
>>> from scipy import linalg
>>> A = mat([[1.0, 1/2.0], [1/2.0, 1/3.0]])
>>> print A
[[ 1.          0.5       ]
 [ 0.5         0.33333333]]
>>> A
matrix([[ 1.        ,  0.5       ],
        [ 0.5       ,  0.33333333]])
>>> lam, v = linalg.eig(A)
>>> lam
array([ 1.26759188+0.j,  0.06574145+0.j])
>>> v
array([[ 0.8816746 , -0.47185793],
       [ 0.47185793,  0.8816746 ]])
>>> v2 = v[:,1]
>>> lambda2 = lam[1]
>>> v2
array([-0.47185793,  0.8816746 ])
>>> lambda2
(0.065741454089335127+0j)
>>> v2 = mat(v2)
>>> v2
matrix([[-0.47185793,  0.8816746 ]])
>>> lambda2*v2.T
matrix([[-0.03102063+0.j],
        [ 0.05796257+0.j]])
>>> A*v2.T
matrix([[-0.03102063],
        [ 0.05796257]])
>>> A*v2.T - lambda2*v2.T
matrix([[ -1.73472348e-17+0.j],
        [ -2.08166817e-17+0.j]])




* GSL 라이브러리를 이용하여 행렬의 고유값과 고유벡터를 구하는 C언어 소스

/***********************************************
  Filename: eigenvalues-01.c
 
  Purpose:
              Find eigenvalues and eigenvectors by using the GSL library.
              http://www.gnu.org/software/gsl/
  On Window XP & cygwin:
  On Ubuntu
        Compile: gcc -Wall -I/usr/local/include -c eigenvalues-01.c
               Link: gcc -o eigenvalues-01 -L/usr/local/lib eigenvalues-01.o -lgsl -lgslcblas -lm

 On Mac OS X Lion:
        Compile: gcc -Wall -I/usr/local/include -c eigenvalues-01.c
               Link: gcc -o eigenvalues-01 -L/usr/local/lib eigenvalues-01.o -lgsl -lgslcblas -lm
              
  Date: 2011. 10. 20 (Thu)

  Execute: ./eigenvalues-01

  Execution Result:
A =
[ [   1.00000000  0.50000000 ],
  [   0.50000000  0.33333333 ] ]

v1 =
[  -0.47185793
    0.88167460 ]
lambda1 = 0.0657415
A*v1 =
[  -0.03102063
    0.05796257 ]
lambda1*v1 =
[  -0.03102063
    0.05796257 ]
A*v1 - lambda1*v1 =
[   0.00000000
    0.00000000 ]

v2 =
[   0.88167460
    0.47185793 ]
lambda2 = 1.26759
A*v2 =
[   1.11760356
    0.59812327 ]
lambda2*v2 =
[   1.11760356
    0.59812327 ]
A*v2 - lambda2*v2 =
[   0.00000000
    0.00000000 ]
***************************************************/

#include <stdio.h>
#include <string.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_eigen.h>
    
void printVector(char *msg, gsl_vector *x, const char *fmt) {
   if (msg != NULL && strlen(msg) > 0)
       printf("%s", msg);
    size_t n = x->size;
    size_t i;
    printf("[ ");
    printf (fmt, gsl_vector_get(x, 0));
    for (i = 1; i < n; i++) {
        printf (fmt, gsl_vector_get(x, i));
    }
    printf(" ]\n");
}

void printColVector(char *msg, gsl_vector *x, const char *fmt) {
   if (msg != NULL && strlen(msg) > 0)
       printf("%s", msg);
    size_t n = x->size;
    size_t i;
    printf("[ ");
    printf (fmt, gsl_vector_get(x, 0));
    if (n > 0)
        printf ("\n");
    for (i = 1; i < n; i++) {
        printf ("  ");
        printf (fmt, gsl_vector_get(x, i));
        if (i < n - 1)
            printf ("\n");
    }
    printf(" ]\n");
}


void multiplyVectorByScalar(gsl_vector *c, double x, const gsl_vector *a) {
    size_t n = a->size;
    size_t i;
    double v;
    for (i = 0; i < n; i++) {
        v = x*gsl_vector_get(a, i);
        gsl_vector_set(c, i, v);
    }
}

void addVector(gsl_vector *c, const gsl_vector *a, const gsl_vector *b) {
    size_t n = a->size;
    size_t i;
    double v;
    for (i = 0; i < n; i++) {
        v = gsl_vector_get(a, i) + gsl_vector_get (b, i);
        gsl_vector_set(c, i, v);
    }
}
void subtractVector(gsl_vector *c, const gsl_vector *a, const gsl_vector *b) {
    size_t n = a->size;
    size_t i;
    double v;
    for (i = 0; i < n; i++) {
        v = gsl_vector_get(a, i) - gsl_vector_get (b, i);
        gsl_vector_set(c, i, v);
    }
}

void printMatrix(char *msg, gsl_matrix *a, char *fmt) {
    if (msg != NULL && strlen(msg) > 0)
        printf("%s\n", msg);
    size_t m = a->size1, n = a->size2;
    size_t i, j;
    printf("[ [ ");
    printf (fmt, gsl_matrix_get(a, 0, 0));
    for (j = 1; j < n; j++) {
        printf (fmt, gsl_matrix_get(a, 0, j));
    }
    printf(" ]");
    if (m > 1)
        printf(",\n");
    for (i = 1; i < m; i++) {
        printf("  [ ");
        printf (fmt, gsl_matrix_get(a, i, 0));
        for (j = 1; j < n; j++) {
            printf (fmt, gsl_matrix_get(a, i, j));
    }
    printf(" ]");
    if (i < m -1)
        printf(",\n");
    }
    printf(" ]\n");
}

void product(gsl_matrix *c, const gsl_matrix *a, const gsl_matrix *b) {
    size_t m = a->size1, n = a->size2, p = b->size2;
    size_t i, j, k;
    double sum;
    for (i = 0; i < m; i++) {
        for (k = 0; k < p; k++) {
            sum = 0.0;
            for (j = 0; j < n; j++) {
                sum = sum + gsl_matrix_get(a, i, j)*gsl_matrix_get(b, j, k);
            }
            gsl_matrix_set (c, i, k, sum);
        }
    }
}

void productWIthRightVector(gsl_vector *c, const gsl_matrix *a, const gsl_vector *b) {
    size_t m = a->size1, n = b->size;
    size_t i, j;
    double sum;
    for (i = 0; i < m; i++) {
        sum = 0.0;
        for (j = 0; j < n; j++) {
            sum = sum + gsl_matrix_get(a, i, j)*gsl_vector_get(b, j);
        }
        gsl_vector_set(c, i, sum);
    }
}

void productWIthLeftVector(gsl_vector *c, const gsl_vector *a, const gsl_matrix *b) {
    size_t m = a->size, n = b->size2;
    size_t i, j;
    double sum;
    for (j = 0; j < n; j++) {
        sum = 0.0;
        for (i = 0; i < m; i++) {
            sum = sum + gsl_vector_get(a, j)*gsl_matrix_get(b, i, j);
        }
        gsl_vector_set(c, j, sum);
    }
}

void add(gsl_matrix *c, const gsl_matrix *a, const gsl_matrix *b) {
    size_t m = a->size1, n = a->size2;
    size_t i, j;
    double v;
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            v = gsl_matrix_get (a, i, j) + gsl_matrix_get (b, i, j);
         gsl_matrix_set (c, i, j, v);
  }
 }
}

void subtract(gsl_matrix *c, const gsl_matrix *a, const gsl_matrix *b) {
    size_t m = a->size1, n = a->size2;
    size_t i, j;
    double v;
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            v = gsl_matrix_get (a, i, j) - gsl_matrix_get (b, i, j);
            gsl_matrix_set (c, i, j, v);
        }
    }
}

void multiply(gsl_matrix *c, double x, const gsl_matrix *a) {
    size_t m = a->size1, n = a->size2;
    size_t i, j;
    double v;
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            v = x*gsl_matrix_get (a, i, j);
            gsl_matrix_set (c, i, j, v);
        }
    }
}

void set(gsl_matrix *c, const gsl_matrix *a) {
    gsl_matrix_memcpy(c, a);
}

double trace(const gsl_matrix *a) {
 size_t m = a->size1;
 size_t i;
 double sum = 0;
    for (i = 0; i < m; i++) {
        sum = sum + gsl_matrix_get (a, i, i);
 }
 return sum;
}

void transpose(gsl_matrix *c, const gsl_matrix *a) {
    size_t m = a->size1, n = a->size2;
    size_t i, j;
    for (i = 0; i < n; i++) {
        for (j = 0; j < m; j++) {
         gsl_matrix_set (c, i, j, gsl_matrix_get (a, j, i));
  }
 }
}

void getQR(gsl_matrix *Q, gsl_matrix *R, const gsl_matrix *A, const gsl_vector *tau) {
   size_t m = A->size1;
   size_t n = A->size2;
   size_t i, j;
   for (i =0 ; i < m; i++) {
       for (j =0 ; j < n; j++) {
           if (i > j) {
               gsl_matrix_set(R, i, j, 0);
               gsl_matrix_set(Q, i, j, gsl_matrix_get(A, i, j));
           }
           else {
               gsl_matrix_set(R, i, j, gsl_matrix_get(A, i, j));
               gsl_matrix_set(Q, i, j, 0);
           }
       }
   }
}

int main (void) {
    double data[] = {    1.0,  1/2.0,
                       1/2.0,  1/3.0   };
    char msg[40];

    gsl_matrix_view A = gsl_matrix_view_array(data, 2, 2);
    gsl_vector *eval = gsl_vector_alloc(2);
    gsl_matrix *evec = gsl_matrix_alloc(2, 2);
    gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(4);
    gsl_eigen_symmv(&A.matrix, eval, evec, w);
    gsl_eigen_symmv_free(w);
    gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_ASC);
    gsl_vector *c = gsl_vector_alloc(2);
    gsl_vector *d = gsl_vector_alloc(2);
    gsl_vector *z = gsl_vector_alloc(2);
    double eval_i;
    gsl_vector_view evec_i;

    printMatrix("A = ", &A.matrix, "%12.8f");
    printf("\n");
    {
         int i;
         for (i = 0; i < 2; i++) {
             eval_i = gsl_vector_get(eval, i);
             evec_i = gsl_matrix_column(evec, i);
             // printf ("v%i = \n", i+1);
             // gsl_vector_fprintf (stdout, &evec_i.vector, "%g");
             sprintf(msg, "v%i = \n", i+1);
             printColVector(msg, &evec_i.vector, "%12.8f");
             printf("lambda%i = %g\n", i+1, eval_i);
   
             productWIthRightVector(c, &A.matrix, &evec_i.vector);
             sprintf(msg, "A*v%i = \n", i+1);
             printColVector(msg, c, "%12.8f");
   
             multiplyVectorByScalar(d, eval_i, &evec_i.vector);
             sprintf(msg, "lambda%i*v%i = \n", i+1, i+1);
             printColVector(msg, d, "%12.8f");
   
             subtractVector(z, c, d);
             sprintf(msg, "A*v%i - lambda%i*v%i = \n", i+1, i+1, i+1);
             printColVector(msg, z, "%12.8f");
             printf("\n");
        }
    }

    
    gsl_vector_free (z);
    gsl_vector_free (d);
    gsl_vector_free (c);
    gsl_vector_free (eval);
    gsl_matrix_free (evec);
    
    return 0;
}


 


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
,