F# 용 소스파일 testForFor.fs 를 OCaml 용으로 수정한 것이다.
F# 언어는 if 구문, for 구문, 들여쓰기 규칙이 Python의 것과 닮았지만, OCam 언어는 (C 언어 처럼) 들여쓰기 규칙이 없다. 그 대신 구문의 끝을 한 개의 세미콜론(;)으로 끝낼지, 두 개의 세미콜론(;;)으로 끝낼지, 아니면 세미콜론을 안 붙일 것이지를 정확하게 지켜야 한다. OCam 언어는 let 으로 시작하는 구문에 세미콜론 없이 예약어 in 으로 (정의가) 계속 이어지는 구문도 많이 쓰인다.

두 개의 세미콜론(;;) 으로 끝나는 곳이 정의가 완전히 끝난 곳임을 알리는 구문이고, 한 개의 세미 콜론으로 끝나는 곳은 정의가 아직 완성 도지 않았으니 무시하라는 구문이다.

 

아래는 ocaml 을 실행시켜서서 (대화영 모드에서) 예약어 in 의 역할을 테스트한 내용이다.

# let z = 2;;
val z : int = 2
# let x = [ 1; 2; 3 ];;
val x : int list = [1; 2; 3]
# let a = let x = 5 in let y = 7 in let z = x + y in 9 + x + y + z;;
val a : int = 33
# a;;
- : int = 33
# x;;
- : int list = [1; 2; 3]
# z;;
- : int = 2
# let a = let x = 5 in let y = 7 in let t = x + y in 9 + x + y + t;;
val a : int = 33
# a;;
- : int = 33
# z;;
- : int = 2
# t;;
Characters 0-1:
  t;;
  ^
Error: Unbound value t

 

OCaml 언어는 (F# 언어 처럼) 함수형 언어기도 하고 명령형 언어이기도 하므로, 여기서는 가급적 OCaml 의 명령형 언어의 특징을 위주로 작성하였다.

  1. (* 
  2.  *  Filename: testForFor.ml
  3.  *
  4.  *         이겹 for 반복문을 사용하여 19단표를 컨솔에 출력한다.
  5.  *
  6.  *   Execute: ocaml testForFor.ml
  7.  *
  8.  *    Or
  9.  *
  10.  *   Compile: ocamlc -o testForFor.exe testForFor.ml
  11.  *   Execute: testForFor
  12.  *
  13.  *  Date:  2013. 1. 27.
  14.  *)
  15. let getDan dan = 
  16.     let t = Array.make 19 "" in
  17.     for j = 0 to (19 - 1) do
  18.         let sa = Printf.sprintf "%2d" dan in
  19.         let sb = Printf.sprintf "%2d" (j + 1) in
  20.         let sval = Printf.sprintf "%3d" (dan*(j + 1)) in
  21.         t.(j) <- Printf.sprintf ("%s x %s = %s") sa sb sval
  22.     done;
  23.     t;;  (* 리턴 값.  함수의 정의가 여기서 완전히 끝나므로 두 개의 세미콜론 *)
  24. (* 19단표를 모두 80컬럼 컨솔에 출력한다. *)
  25. let printAllNineteenDan() =    (* OCaml 소스 코드에서는 (F# 소스 코드에서 처럼) 리스트 대신 배열을 사용한다. *)
  26.     let arr = Array.make_matrix 18 19 "aa" in
  27.     for i = 2 to (20 - 1) do
  28.         arr.(i - 2) <- (getDan i );
  29.     done;
  30.     let d = [| 2; 7; 11; 16 |] in       (* 각 줄단위 블럭의 첫단 *)
  31.     let counter = [| 5; 4; 5; 4 |] in         (* 각 줄단위 블럭에 속한 단의 개수 *)
  32.     let lines = Array.make 19 "" in
  33.     for k = 0 to ((Array.length d) - 1) do
  34.         (* 8-바이트 길이의 한 줄씩 완성 *)
  35.         for i = 0 to (19 - 1) do
  36.             lines.(i) <- (arr.(d.(k)-2).(i));
  37.             for j = 1 to (counter.(k) - 1) do
  38.                 lines.(i) <- Printf.sprintf ("%s   %s") lines.(i) arr.(d.(k)-2+j).(i)
  39.             done;
  40.         done;
  41.         (* 80 바이트 길이의 한 줄씩 출력 *)
  42.         for i = 0 to (19 - 1) do
  43.             Printf.printf "%s\n" (lines.(i))
  44.         done;
  45.         Printf.printf "\n";
  46.     done;;
  47. printAllNineteenDan();;


컴파일: 
Prompt> ocamlc -o testForFor.exe testForFor.ml 

실행: 
Prompt> testForFor 
 2 x  1 =   2    3 x  1 =   3    4 x  1 =   4    5 x  1 =   5    6 x  1 =   6
 2 x  2 =   4    3 x  2 =   6    4 x  2 =   8    5 x  2 =  10    6 x  2 =  12
 2 x  3 =   6    3 x  3 =   9    4 x  3 =  12    5 x  3 =  15    6 x  3 =  18
 2 x  4 =   8    3 x  4 =  12    4 x  4 =  16    5 x  4 =  20    6 x  4 =  24
 2 x  5 =  10    3 x  5 =  15    4 x  5 =  20    5 x  5 =  25    6 x  5 =  30
 2 x  6 =  12    3 x  6 =  18    4 x  6 =  24    5 x  6 =  30    6 x  6 =  36
 2 x  7 =  14    3 x  7 =  21    4 x  7 =  28    5 x  7 =  35    6 x  7 =  42
 2 x  8 =  16    3 x  8 =  24    4 x  8 =  32    5 x  8 =  40    6 x  8 =  48
 2 x  9 =  18    3 x  9 =  27    4 x  9 =  36    5 x  9 =  45    6 x  9 =  54
 2 x 10 =  20    3 x 10 =  30    4 x 10 =  40    5 x 10 =  50    6 x 10 =  60
 2 x 11 =  22    3 x 11 =  33    4 x 11 =  44    5 x 11 =  55    6 x 11 =  66
 2 x 12 =  24    3 x 12 =  36    4 x 12 =  48    5 x 12 =  60    6 x 12 =  72
 2 x 13 =  26    3 x 13 =  39    4 x 13 =  52    5 x 13 =  65    6 x 13 =  78
 2 x 14 =  28    3 x 14 =  42    4 x 14 =  56    5 x 14 =  70    6 x 14 =  84
 2 x 15 =  30    3 x 15 =  45    4 x 15 =  60    5 x 15 =  75    6 x 15 =  90
 2 x 16 =  32    3 x 16 =  48    4 x 16 =  64    5 x 16 =  80    6 x 16 =  96
 2 x 17 =  34    3 x 17 =  51    4 x 17 =  68    5 x 17 =  85    6 x 17 = 102
 2 x 18 =  36    3 x 18 =  54    4 x 18 =  72    5 x 18 =  90    6 x 18 = 108
 2 x 19 =  38    3 x 19 =  57    4 x 19 =  76    5 x 19 =  95    6 x 19 = 114

 7 x  1 =   7    8 x  1 =   8    9 x  1 =   9   10 x  1 =  10
 7 x  2 =  14    8 x  2 =  16    9 x  2 =  18   10 x  2 =  20
 7 x  3 =  21    8 x  3 =  24    9 x  3 =  27   10 x  3 =  30
 7 x  4 =  28    8 x  4 =  32    9 x  4 =  36   10 x  4 =  40
 7 x  5 =  35    8 x  5 =  40    9 x  5 =  45   10 x  5 =  50
 7 x  6 =  42    8 x  6 =  48    9 x  6 =  54   10 x  6 =  60
 7 x  7 =  49    8 x  7 =  56    9 x  7 =  63   10 x  7 =  70
 7 x  8 =  56    8 x  8 =  64    9 x  8 =  72   10 x  8 =  80
 7 x  9 =  63    8 x  9 =  72    9 x  9 =  81   10 x  9 =  90
 7 x 10 =  70    8 x 10 =  80    9 x 10 =  90   10 x 10 = 100
 7 x 11 =  77    8 x 11 =  88    9 x 11 =  99   10 x 11 = 110
 7 x 12 =  84    8 x 12 =  96    9 x 12 = 108   10 x 12 = 120
 7 x 13 =  91    8 x 13 = 104    9 x 13 = 117   10 x 13 = 130
 7 x 14 =  98    8 x 14 = 112    9 x 14 = 126   10 x 14 = 140
 7 x 15 = 105    8 x 15 = 120    9 x 15 = 135   10 x 15 = 150
 7 x 16 = 112    8 x 16 = 128    9 x 16 = 144   10 x 16 = 160
 7 x 17 = 119    8 x 17 = 136    9 x 17 = 153   10 x 17 = 170
 7 x 18 = 126    8 x 18 = 144    9 x 18 = 162   10 x 18 = 180
 7 x 19 = 133    8 x 19 = 152    9 x 19 = 171   10 x 19 = 190

11 x  1 =  11   12 x  1 =  12   13 x  1 =  13   14 x  1 =  14   15 x  1 =  15
11 x  2 =  22   12 x  2 =  24   13 x  2 =  26   14 x  2 =  28   15 x  2 =  30
11 x  3 =  33   12 x  3 =  36   13 x  3 =  39   14 x  3 =  42   15 x  3 =  45
11 x  4 =  44   12 x  4 =  48   13 x  4 =  52   14 x  4 =  56   15 x  4 =  60
11 x  5 =  55   12 x  5 =  60   13 x  5 =  65   14 x  5 =  70   15 x  5 =  75
11 x  6 =  66   12 x  6 =  72   13 x  6 =  78   14 x  6 =  84   15 x  6 =  90
11 x  7 =  77   12 x  7 =  84   13 x  7 =  91   14 x  7 =  98   15 x  7 = 105
11 x  8 =  88   12 x  8 =  96   13 x  8 = 104   14 x  8 = 112   15 x  8 = 120
11 x  9 =  99   12 x  9 = 108   13 x  9 = 117   14 x  9 = 126   15 x  9 = 135
11 x 10 = 110   12 x 10 = 120   13 x 10 = 130   14 x 10 = 140   15 x 10 = 150
11 x 11 = 121   12 x 11 = 132   13 x 11 = 143   14 x 11 = 154   15 x 11 = 165
11 x 12 = 132   12 x 12 = 144   13 x 12 = 156   14 x 12 = 168   15 x 12 = 180
11 x 13 = 143   12 x 13 = 156   13 x 13 = 169   14 x 13 = 182   15 x 13 = 195
11 x 14 = 154   12 x 14 = 168   13 x 14 = 182   14 x 14 = 196   15 x 14 = 210
11 x 15 = 165   12 x 15 = 180   13 x 15 = 195   14 x 15 = 210   15 x 15 = 225
11 x 16 = 176   12 x 16 = 192   13 x 16 = 208   14 x 16 = 224   15 x 16 = 240
11 x 17 = 187   12 x 17 = 204   13 x 17 = 221   14 x 17 = 238   15 x 17 = 255
11 x 18 = 198   12 x 18 = 216   13 x 18 = 234   14 x 18 = 252   15 x 18 = 270
11 x 19 = 209   12 x 19 = 228   13 x 19 = 247   14 x 19 = 266   15 x 19 = 285

16 x  1 =  16   17 x  1 =  17   18 x  1 =  18   19 x  1 =  19
16 x  2 =  32   17 x  2 =  34   18 x  2 =  36   19 x  2 =  38
16 x  3 =  48   17 x  3 =  51   18 x  3 =  54   19 x  3 =  57
16 x  4 =  64   17 x  4 =  68   18 x  4 =  72   19 x  4 =  76
16 x  5 =  80   17 x  5 =  85   18 x  5 =  90   19 x  5 =  95
16 x  6 =  96   17 x  6 = 102   18 x  6 = 108   19 x  6 = 114
16 x  7 = 112   17 x  7 = 119   18 x  7 = 126   19 x  7 = 133
16 x  8 = 128   17 x  8 = 136   18 x  8 = 144   19 x  8 = 152
16 x  9 = 144   17 x  9 = 153   18 x  9 = 162   19 x  9 = 171
16 x 10 = 160   17 x 10 = 170   18 x 10 = 180   19 x 10 = 190
16 x 11 = 176   17 x 11 = 187   18 x 11 = 198   19 x 11 = 209
16 x 12 = 192   17 x 12 = 204   18 x 12 = 216   19 x 12 = 228
16 x 13 = 208   17 x 13 = 221   18 x 13 = 234   19 x 13 = 247
16 x 14 = 224   17 x 14 = 238   18 x 14 = 252   19 x 14 = 266
16 x 15 = 240   17 x 15 = 255   18 x 15 = 270   19 x 15 = 285
16 x 16 = 256   17 x 16 = 272   18 x 16 = 288   19 x 16 = 304
16 x 17 = 272   17 x 17 = 289   18 x 17 = 306   19 x 17 = 323
16 x 18 = 288   17 x 18 = 306   18 x 18 = 324   19 x 18 = 342
16 x 19 = 304   17 x 19 = 323   18 x 19 = 342   19 x 19 = 361



 

Posted by Scripter
,

소스 파일명: TestNoWhile.ml

  1. (*
  2.  *  Filename: testNoWhile.ml
  3.  *
  4.  *  Purpose:  Example not using the while loop syntax 
  5.  *                while ....
  6.  * 
  7.  *  Execute: ocaml testNoWhile.ml -200 300
  8.  * 
  9.  *    Or
  10.  * 
  11.  *  Compile: ocamlc -o testNoWhile.exe testNoWhile.ml
  12.  *  Execute: testNoWhile -200 300
  13.  *)
  14. (* 사용법 표시 *)
  15. let printUsage() =
  16.     Printf.printf "Using: testNoWhile.py [integer1] [integer2]\n";
  17.     Printf.printf "This finds the greatest common divisor of the given two integers.\n";;
  18. let cmdArgs = Sys.argv;; 
  19. if not ((Array.length cmdArgs) == 3) then
  20.     printUsage();
  21. if not ((Array.length cmdArgs) == 3) then
  22.     exit 1;;
  23. (*
  24. // --------------------------------------
  25. // 명령행 인자의 두 스트링을 가져와서
  26. // 정수 타입으로 변환하여
  27. // 변수 val1과 val2에 저장한다.
  28. *)
  29. let val1 = int_of_string cmdArgs.(1);;
  30. let val2 = int_of_string cmdArgs.(2);;
  31. let a = ref (abs val1);;
  32. let b = ref (abs val2);;
  33. let max x y = if y > x then y else x;;
  34. let min x y = if y > x then x else y;;
  35. let maxab = max !a !b;;
  36. let minab = min !a !b;;
  37. (* a는 |val1|, |val2| 중 큰 값 *)
  38. a := maxab;;
  39. b := minab;;
  40. (*
  41. // --------------------------------------
  42. // 재귀호출 Euclidean 알고리즘
  43. //
  44. //     Euclidean 알고리즘의 반복 (나머지가 0이 될 때 까지)
  45. //     나머지가 0이면 그 때 나눈 수(제수) x가 최대공약수(GCD)이다.
  46.  *)
  47. let rec gcdRecursive x y =
  48.     match y with
  49.     | 0 -> x
  50.     | _ -> gcdRecursive y (x mod y);;
  51. let gcd = gcdRecursive !a !b;;
  52. (* 최대공약수(GCD)를 출력한다. *)
  53. Printf.printf "GCD(%d, %d) = %d\n" val1 val2 gcd;
  54. exit 0;;

 

컴파일:
Command> ocamlc -o testNoWhile.exe testNoWhile.fs

실행:
Command> testNoWhile
Using: testNoWhile [integer1] [integer2]
This finds the greatest common divisor of the given two integers.

Command> testNoWhile -200 300
GCD(-200, 300) = 100

Command> testNoWhile -200 0
GCD(-200, 0) = 200

Command> testNoWhile 125 100
GCD(125, 100) = 25

Command> testNoWhile 23 25
GCD(23, 25) = 1



Posted by Scripter
,

소스 파일명: testWhile.ml

  1. (*
  2.  *  Filename: testWhile.ml
  3.  *
  4.  *  Purpose:  Example using the while loop syntax
  5.  *                while ....
  6.  * 
  7.  *  Execute: ocaml testWhile.ml -200 300
  8.  * 
  9.  *    Or
  10.  * 
  11.  *  Compile: ocamlc -o testWhile.exe testWhile.ml
  12.  *  Execute: testWhile -200 300
  13.  *)
  14. (* 사용법 표시 *)
  15. let printUsage() =
  16.     Printf.printf "Using: testWhile.py [integer1] [integer2]\n"; 
  17.     Printf.printf "This finds the greatest common divisor of the given two integers.\n";;
  18. let cmdArgs = Sys.argv;;
  19. if not ((Array.length cmdArgs) = 3) then
  20.     printUsage();;
  21. if not ((Array.length cmdArgs) == 3) then
  22.     exit 1;;
  23. (*
  24. // --------------------------------------
  25. // 명령행 인자의 두 스트링을 가져와서
  26. // 정수 타입으로 변환하여
  27. // 변수 val1과 val2에 저장한다.
  28. *)
  29. let val1 = int_of_string cmdArgs.(1);;
  30. let val2 = int_of_string cmdArgs.(2);;
  31. (* a는 |val1|, |val2| 중 큰 값 *)
  32. let a = ref (abs val1);;
  33. let b = ref (abs val2);;
  34. if (!a < !b) then
  35.     let t = !a in
  36.     a := abs val2;
  37.     b := t;;
  38. if (!b = 0) then
  39.     Printf.printf "GCD(%d, %d) = %d\n" val1 val2 !a;;
  40. if (!b = 0) then
  41.     exit 0;;
  42. (*
  43. // --------------------------------------
  44. // Euclidean 알고리즘의 시작
  45. //
  46. // a를 b로 나누어 몫은 q에, 나머지는 r에 저장
  47. *)
  48. let q = ref (!a / !b);;
  49. let r = ref (!a mod !b);;
  50. (*
  51. // --------------------------------------
  52. // Euclidean 알고리즘의 반복 (나머지 r이 0이 될 때 까지)
  53. *)
  54. while not (!r = 0) do
  55.     a := !b;
  56.     b := !r;
  57.     q := !a / !b;
  58.     r := !a mod !b;
  59. done;;
  60. (* 나머지가 0이면 그 때 나눈 수(제수) b가 최대공약수(GCD)이다. *)
  61. let gcd = !b;;
  62. (* 최대공약수(GCD)를 출력한다. *)
  63. Printf.printf "GCD(%d, %d) = %d\n" val1 val2 gcd;;



컴파일:

Command> ocamlc -o testWhile.exe testWhile.ml

실행:

Command> testWhile
Using: TestWhile [integer1] [integer2]
This finds the greatest common divisor of the given two integers.

Command> testWhile -200 300
GCD(-200, 300) = 100

Command> testWhile -200 0
GCD(-200, 0) = 200

Command> testWhile 125 100
GCD(125, 100) = 25

Command> testWhile 23 25
GCD(23, 25) = 1



Posted by Scripter
,

OCaml 언어는 함수형 언어이면서도 명령형 언어의 특징을 대부분 가지고 잇다.
따라서 보통의 for 구문을 쓸 수도 있고, 재귀호출 함수릉 만들어 쓸 수도 있다.

아래의 소스에서 함수 printDan 은 보통의 for 구문을 쓴 것이고
함수 printAnotherDan 은 재귀호출 함수를 쓴 것이다.


소스 파일명: forTest.ml
------------------------------[소스 시작]
(*
   Filename: forTest.ml
 
   Execute: ocaml forTest.ml

     Or
 
   Compile: ocamlc -o forTest forTest.ml
   Execute: ./forTest
 
     Or
 
   Compile: ocamlc -o forTest.exe forTest.ml
   Execute: forTest
 
   Date: 2013. 1. 26.
   Copyright (c) pkim _AT_ scripts.pe.kr
*)

let printDan dan =
    for i = 1 to 9 do
        Printf.printf "%d x %d = %2d\n" dan i (dan*i)
    done;;

let printAnotherDan dan =
    let rec loop l =
        match l with
        [] -> []
        | x :: xs -> Printf.printf "%d x %d = %2d\n" dan x (dan*x); loop xs
    in
    loop (Array.to_list (Array.init 9 (fun x -> x + 1)));;
    (* loop [ 1; 2; 3; 4; 5; 6; 7; 8; 9 ];; *)


printDan 2;;
print_newline();;
printAnotherDan 3;;
print_newline();;
------------------------------[소스 끝]


컴파일> ocamlc -o forTest.exe forTest.ml

실행> forTest
2 x 1 =  2
2 x 2 =  4
2 x 3 =  6
2 x 4 =  8
2 x 5 = 10
2 x 6 = 12
2 x 7 = 14
2 x 8 = 16
2 x 9 = 18

3 x 1 =  3
3 x 2 =  6
3 x 3 =  9
3 x 4 = 12
3 x 5 = 15
3 x 6 = 18
3 x 7 = 21
3 x 8 = 24
3 x 9 = 27


 

Posted by Scripter
,

 

소스 파일명: testArguments.ml

  1. (*
  2.    Filename: testArguments.ml
  3.    Execute: ocaml testArguments.ml 1.2 2.1 3.00
  4.      Or
  5.    Compile: ocamlc -o testArguments testArguments.ml
  6.    Execute: ./pyramidOfDigits2 1.2 2.1 3.00
  7.      Or
  8.    Compile: ocamlc -o testArguments.exe testArguments.ml
  9.    Execute: testArguments 1.2 2.1 3.00
  10.    Date: 2013. 1. 26.
  11.    Copyright (c) pkim _AT_ scripts.pe.kr
  12. *)
  13. let main() =
  14.     let args = Sys.argv in
  15.     let args1 = Array.to_list args in
  16.     let arr1 = List.tl args1 in
  17.     let arr = List.map float_of_string arr1 in
  18.     Printf.printf "Count of arguments: %d\n" (List.length arr);
  19.     Printf.printf "The sum of arguments is %g\n" (List.fold_right (+.) arr 0.0);
  20.     print_newline();;
  21. main();;

 

컴파일> ocamlc -o testArguments.exe testArguments.nl

실행> testArguments 5.2 7.9 -1.21
Count of arguments: 3
The sum of arguments is 11.89


 

Posted by Scripter
,


소스 파일명: testIf.ml

  1. (*
  2.    Filename: testIf.ml
  3.    Execute: ocaml testIf.ml -8e-2
  4.      Or
  5.    Compile: ocamlc -o testIf.ml
  6.    Execute: ./testIf -8e-2
  7.      Or
  8.    Compile: ocamlc -o testIf.exe testIf.ml
  9.    Execute: testIf -8e-2
  10.    Date: 2013. 1. 26.
  11.    Copyright (c) pkim _AT_ scripts.pe.kr
  12. *)
  13. let printUsing() =
  14.      Printf.printf "Using: testIf [number]\n";
  15.      Printf.printf "   or  ./testIf [number]\n";
  16.      Printf.printf "   or  ocaml testIf.ml [number]\n";
  17.      Printf.printf "This determines whether the number is positive or not.\n";;
  18. let isPositve = function
  19.      | x when x > 0.0 -> "positive";
  20.      | x when x < 0.0 -> "negative" ;
  21.      | x when x = 0.0 -> "zero" ;
  22.      | _ -> "not a floating number";;
  23. let main () =
  24.     print_int(Array.length Sys.argv);;
  25.     if ((Array.length Sys.argv) < 2) then
  26.         printUsing()
  27.     else
  28.         let arg = float_of_string Sys.argv.(1) in
  29.         let msg = isPositve(arg) in
  30.         Printf.printf "%g is %s." arg msg;
  31.         print_newline();;
  32.     exit 0;;
  33. main ();;



컴파일> ocamlc -o testIf.exe testIf.ml

실행> testIf -1.2
-1.2 is negative.


실행> testIf 0.0
0 is zero.


실행> testIf -0.1e-127
-1e-128 is negative.


Posted by Scripter
,

1. mpir 은 gmp 대신사용하는 (C/C++ 언어용) 긴 자리 수치 처리를 위한 기본 연산 라이브러리이다.

   자리수가 매우 긴 정수, 유리수, 소수점수를 계산할 수 있다.

2. xmpir 은 (C 언어용 긴 자리 수치 라이브러리인) mpir 의 래퍼(wrapper) 이다.

3. xmpir 은  xmpir 다운로드 에서 구할 수 있다.

(주의 사항. dl4windows.dll 파일이 존재하는 폴더의 경로명에 #문자가 있으면 컴파일은 되나 실행 시에 에러에 걸린다. 그 이유는 xmpir 이 dl4windows.dll 파일을 찾을 때 URL 주소를 적용해서 찾기 때문이다.)

 

실행에 필요한 *.dll 파일들은 (현재 경로 또는) 환경변수 PATH 에 결린 경로의 폴더에 존재해야 한다.

  • dl4windows.dll  : 윈도우 계열의 닷넷 에서 실행될 때 xmpir 이 찾는 파일
  • dl4linux.dll  : 리눅스 계열의 mono 에서 실행될 때 xmpir 이 찾는 파일
  • xmpir32.dll : 32 비트 윈도우 또는 리눅스에서 실행될 때 PATH 걸린 폴더에 있어야 하는 파일
  • xmpir64.dll : 64 비트 윈도우 또는 리눅스에서 실행될 때 PATH 걸린 폴더에 있어야 하는 파일
  • src\xmpir,cs : 컴파일할 때 함께 사용되어야 하는 파일

 

demo 폴더에서 demo,cs 컴파일하기

    Prompt> csc demo.cs ..\src\xmpir.cs

 

xmpir 을 이용하는 예제 소스 파일 (파일명: demo.cs)

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Diagnostics;
class MyClass
{
    [STAThread]
    static void Main(string[] args)
    {
        mpir.mpz_t f = mpir.mpz_init_set_ui(1);
        int i;
        for(i=2; i<=30; i++)
            mpir.mpz_mul_si(f, f, i);
        System.Console.Write("30! = ");
        System.Console.WriteLine(mpir.mpz_get_string(10,f));
        mpir.mpz_clear(f);        
    }
}

 

실행 결과: 30! = 265252859812191058636308480000000

 

Posted by Scripter
,

 

C 언어로 배정밀도 부동소수점수(floating point number of double type)로 높은 차수의 다항식 값을 계산을 하는 경우의 오차에 대하여 생각해보기로 하자. 우선 0.7 을 (배정밀도이든 단정밀도이든 상관없이) 부동소수점수로 정확하게 기억시키는 방법은 없다. 0.7 을 배정밀도 부동소수점수(double 타입의 수)로 처리하여 십진법수로 표현하면 유효숫자가 겨우 14개 내지 15개 정도 밖에 되지 않는다.  수 1 에 비하여 오차 1.0e-15 는 상대적으로 매우 작은 오차이다. 그러나 차수가 매우 높은 다항식 함수는 아주 짧은 구간(간격이 약 1.0e-15  인 구간) 안에서도 매우 많은 진동을 하여 함수값의 차이는 매우 커질 수가 있으니 주의해야 한다.

식 f(x) = 2*x*x - 1 로 정의되는 함수 f 를 생각해 보자. x 가 폐구간 [-1,1] 안에 있으면 f(x) 도 이 구간 안에 있다. 즉 f 는 f : [-1, 1] -> [-1, 1] 인 함수이다. 더군다나 이 함수는 두 개의 부동점(fixed point, 즉 f(x) = x 인 x)을 갖는 함수이다. 방정식 2*x*x - 1 = x 플 풀면 근이 -0.5 와 1 이다, 실제로 f(1) = 1 이고 f(-0.5) = -0.5 이다. 이제 53 개의 f 를 반복해서 합성한 함수를 g 로 놓고  g(0.7) 을 계산해 보자. g(0.7) 의 값의 오차가 어떠할런지... 

아래는 C 언어로 g(0.7) = f^(53) (0.7) 을 계산해 본 소스이다. 결과는 참값에 비하여 오차가 너무 큰 근사값(즉 유효하지 않은 근사값))이 된다는 것이다. 참고로 g(x) 는 2^53 차(즉, 9007199254740992 차)의 다항식 함수이다.

 

//  Filename: AccumulativeError07.c
//
//          This illustrates that a tiny error gives a big error
//          in the evaluation of a polynomial of very high degree,
//
//   Compile: gcc AccumulativeError07 AccumulativeError07.c
//   Execute: ./AccumulativeError07
//
//     Or
//
//   Compile: cl AccumulativeError07.c
//   Execute: AccumulativeError07
//
//  Date: 2013. 1. 22.
//  Copyright (c) 2013 PH Kim  (pkim __AT__ scripts.pe.kr)


#include <stdio.h>

#define REPEAT 53

double f(double x)
{
    return 2.0*x*x - 1.0;
}

int main()
{
    double x = 0.7;
    double y, t;
    int i;

    printf("x = %g\n", x);
    printf("x = %f\n", x);
    printf("x = %.15f\n", x);
    printf("x = %.16f\n", x);
    printf("x = %.20f\n", x);
    printf("\n");

    printf("f is a function defined by f(x) = 2*x*x - 1\n");
    printf("f^(n) (x) means the n times composite of the function f(x),\n");
    printf("say, f^(2) (x) = f(f(x)), f^(2) (x) = f(f(f(x))), and etc\n");
    printf("\n");

    t = x;
    for (i = 1; i <= REPEAT; i++) {
        y = f(t);
        t = y;
    }

    printf("y = f^(53) (x) = f^(53) (%g) = %g\n", x, y);
    printf("y = f^(53) (x) = f^(53) (%g) = %f\n", x, y);
    printf("y = f^(53) (x) = f^(53) (%g) = %.15f\n", x, y);
    printf("y = f^(53) (x) = f^(53) (%g) = %.16f\n", x, y);
    printf("y = f^(53) (x) = f^(53) (%g) = %.20f\n", x, y);
    printf("Is it true?\n");
    printf("\n");

    printf("Its error is too big.\nThe iterated value shoul be -0.5671977142553364749...\n");
    printf("\n");

    return 0;
}

/*
Output:
x = 0.7
x = 0.700000
x = 0.700000000000000
x = 0.7000000000000000
x = 0.69999999999999996000

f is a function defined by f(x) = 2*x*x - 1
f^(n) (x) means the n times composite of the function f(x),
say, f^(2) (x) = f(f(x)), f^(2) (x) = f(f(f(x))), and etc

y = f^(53) (x) = f^(53) (0.7) = 0.538614
y = f^(53) (x) = f^(53) (0.7) = 0.538614
y = f^(53) (x) = f^(53) (0.7) = 0.538614158130321
y = f^(53) (x) = f^(53) (0.7) = 0.5386141581303205
y = f^(53) (x) = f^(53) (0.7) = 0.53861415813032054000
Is it true?

Its error is too big.
The iterated value shoul be -0.5671977142553364749...
*/

 

 

 

Posted by Scripter
,

C 언어로 작성된 다음 소스를 컴파일하여 실행하면 숫자 계산으로 쌓아 올린 피라미드 세 가지가 출력된다. (gcc 는 GNU C 컴파일러의 컴파일 명령이고, cl 은 Visual C++ 컴파일러의 컴파일 명령이다.)

세 함수 pyra1(int, int), pyra2(int, int), pyra3(int, int) 은 재귀호출을 사용하였고, 세 함수 pyramid1(), pyramid2(), pyramid3() 은 for 반복문을 사용하였다.

 

//  Filename: pyramidOfDigits2.c
//
//   Compile: gcc -o pyramidOfDigits2 pyramidOfDigits2.c
//   Execute: ./pyramidOfDigits2
//
//     Or
//
//   Compile: cl pyramidOfDigits2.c
//   Execute: pyramidOfDigits2
//
//     See: http://darvish.wordpress.com/2008/03/16/the-beauty-of-mathematics-and-the-love-of-god/
//
//  Date: 2013. 1. 22.
//  Copyright (c) 2013 PH Kim  (pkim __AT__ scripts.pe.kr)


#include <stdio.h>

#define TEN    10
#define NINE   9
#define EIGHT   8

// initial calling: pyra1(1, 1)
void pyra1(int n, int i)
{
    if (i <= NINE) {
        printf("%9d x %d + %d = %d\n", n, EIGHT, i, n*EIGHT + i);
        if (i < NINE) {
            pyra1(n*TEN + (i + 1), i + 1);
        }
    }
}

// initial calling: pyra2(9, 7)
void pyra2(int n, int i)
{
    if (i >= 0) {
        printf("%8d x %d + %d = %d\n", n, NINE, i, n*NINE + i);
        if (i > 0) {
            pyra2(n*TEN + (i + 1), i - 1);
        }
    }
}

// initial calling: pyra3(1, 2)
void pyra3(int n, int i)
{
    if (i <= TEN) {
        printf("%9d x %d + %2d = %d\n", n, NINE, i, n*NINE + i);
        if (i < TEN) {
            pyra3(n*TEN + i, i + 1);
        }
    }
}

void pyramid1()
{
    int i, n;
    char s[TEN];

    for (i = 1; i < TEN; i++) {
        s[i - 1] = (char) (48 + i);
        s[i] = '\0';
        sscanf(s, "%d", &n);
        printf("%9d x %d + %d = %d\n", n, EIGHT, i, n*EIGHT + i);
    }
}

void pyramid2()
{
    int i, n;
    char s[TEN];

    for (i = NINE; i > 1; i--) {
        s[NINE - i] = (char) (48 + i);
        s[NINE - i + 1] = '\0';
        sscanf(s, "%d", &n);
        printf("%8d x %d + %d = %d\n", n, NINE, i - 2, n*NINE + (i - 2));
    }
}

void pyramid3()
{
    int i, n;
    char s[TEN];

    for (i = 1; i < TEN; i++) {
        s[i - 1] = (char) (48 + i);
        s[i] = '\0';
        sscanf(s, "%d", &n);
        printf("%9d x %d + %2d = %d\n", n, NINE, i + 1, n*NINE + (i + 1));
    }
}

int main()
{
    printf("Use for loops\n");
    printf("Pyramid 1\n");
    pyramid1();
    printf("\n");

    printf("Pyramid 2\n");
    pyramid2();
    printf("\n");

    printf("Pyramid 3\n");
    pyramid3();
    printf("\n");


    printf("Use recursively called functions\n");
    printf("Pyramid 1\n");
    pyra1(1, 1);
    printf("\n");

    printf("Pyramid 2\n");
    pyra2(9, 7);
    printf("\n");

    printf("Pyramid 3\n");
    pyra3(1, 2);
    printf("\n");

    return 0;
}

 

 

 

Posted by Scripter
,

Jython 2.5.2 를 쓰는데, 명령창에서 jython 만 실행하고 나면, 환경변수 JAVA_HOME 이 바뀌어서 계속해서 자바 소스를 컴파일하거나 Groovy 를 사용하는데 문제를 일으킨다.

이럴 때는 경로 %JYTHON_HOME% 에 있는 jython.bat 파일의 5째 줄

set JAVA_HOME="C:\Program Files\Java\jre7"

set JAVA_HOME="내게 맞는 경로"    REM 예: "C:\Java7"

로 고친다.

--------------

위의 현상은 최신 버전인 Jython 2.5.3 에서도 마찬가지인데, Jython 인스톨러로 성치하는 과정에서 JAVA_HOME 을 바로 설정해주면 저런 현상(JAVA_HOME 이 바뀌는 문제)은 일어나지 않는다. 그러나 Java  SDK 를 다른 곳에 새로 설치하거나 하면, 또 jython.bat 파일을 위와 같이 손봐주어야 한다.

 


 

Posted by Scripter
,