다음은 초등학교에서 배우는 나눗셈 계산표를 만들어주는 OCaml 소스 코드이다.
나눗셈 계산표를 완성하고 나서 약수, 배수 관계를 알려준다.
아래의 소스는 Python 용 소스를 F# 용 소스로 거의 일대일 변환하고,또 F# 소스를 OCaml 소스로 변환한 것이라서, OCaml 언어의 명령형 언어의 특징을 위주로 짜여져 있다.
예외상황 처리 부분 try ... with ... 부분이 아직 미완성이다.
- (*
- * Filename: makeDivisionTable.ml
- *
- * Purpose: Make a division table in a handy written form.
- *
- * Execute: ocaml makeDivisionTable.ml
- *
- * Or
- *
- * Compile: ocamlc -o makeDivisionTable.exe makeDivisionTable.ml
- * Execute: makeDivisionTable 12345 32
- * makeDivisionTable 500210 61
- * makeDivisionTable 234 55
- *
- * Date: 2013. 2. 2.
- * Author: pkim __AT__ scripts.pe.kr
- *)
- open Printf ;;
- exception RuntimeError of string
- exception ValueError of string
- let sBASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;;
- let sSPACE = " " ;;
- let sULINE = "__________________________________________________________" ;;
- let sHIPHEN = "----------------------------------------------------------" ;;
- let println s = printf "%s\n" s ;;
- let print s = printf "%s" s ;;
- let printUsage() =
- (* print("Using: makeDivisionTable [numerator] [denominator]") *)
- (* print("Make a division table in a handy written form.") *)
- println "사용법: makeDivisionTable [피제수] [제수]" ;
- println "손으로 작성한 형태의 나눗셈 표를 만들어준다." ;;
- let simplify v width =
- let t = [| string_of_int v |] in
- let slen = (String.length t.(0)) in
- if slen < width then begin
- t.(0) <- (String.sub sSPACE 0 (width - slen)) ^ t.(0)
- end ;
- t.(0) ;;
- let getSuffix v =
- let t = v mod 10 in
- let suffix = [| "은" |] in
- if (String.contains "2459" (string_of_int t).[0]) then begin
- suffix.(0) <- "는" ;
- end ;
- suffix.(0) ;;
- let makeTable numer denom quotient =
- let strNumer = sprintf "%d" numer in
- let strDenom = sprintf "%d" denom in
- let strQuotient = sprintf "%d" quotient in
- let lenN = String.length strNumer in
- let lenD = String.length strDenom in
- let lenQ = String.length strQuotient in
- let offsetLeft = 3 + lenD + 3 in
- let spaces = " " in
- let uline = String.sub sULINE 0 (lenN + 2) in
- let sline = String.sub sHIPHEN 0 lenN in
- let bias = lenN - lenQ in
- println ((String.sub spaces 0 offsetLeft) ^ (String.sub spaces 0 bias) ^ (sprintf "%d" quotient)) ;
- println ((String.sub spaces 0 (offsetLeft - 2)) ^ uline) ;
- print (" " ^ strDenom ^ " ) " ^ strNumer) ;
- let strTmpR = [| String.sub strNumer 0 (bias + 1) |] in
- let tmpR = ref (int_of_string strTmpR.(0)) in
- let tmpSub = ref 0 in
- let oneDigit = [| "" |] in
- for i = 0 to (lenQ - 1) do
- if (String.sub strQuotient i 1) = "0" then begin
- if i + 1 < lenQ then begin
- oneDigit.(0) <- (String.sub strNumer (bias + i + 1) 1) ;
- printf "%s" oneDigit.(0) ;
- strTmpR.(0) <- (strTmpR.(0) ^ oneDigit.(0)) ;
- tmpR := int_of_string strTmpR.(0)
- end
- end
- else begin
- print_newline() ;
- tmpSub := (int_of_string (String.sub strQuotient i 1)) * denom ;
- printf "%s\n" ((String.sub spaces 0 offsetLeft) ^ (simplify !tmpSub (bias + i + 1))) ;
- printf "%s\n" ((String.sub spaces 0 offsetLeft) ^ sline) ;
- tmpR := !tmpR - !tmpSub ;
- if !tmpR = 0 && i + 1 < lenQ then begin
- printf "%s" ((String.sub spaces 0 offsetLeft) ^ (String.sub spaces 0 (bias + i + 1)) ) ;
- end
- else begin
- printf "%s" ((String.sub spaces 0 offsetLeft) ^ (simplify !tmpR (bias + i + 1))) ;
- end ;
- strTmpR.(0) <- sprintf "%d" !tmpR ;
- if i + 1 < lenQ then begin
- oneDigit.(0) <- (String.sub strNumer (bias + i + 1) 1) ;
- if (String.length oneDigit.(0)) > 0 then
- print oneDigit.(0) ;
- strTmpR.(0) <- (strTmpR.(0) ^ oneDigit.(0))
- end ;
- tmpR := int_of_string strTmpR.(0)
- end
- done ;
- printf "\n" ;
- !tmpR ;;
- let main() =
- let cmdArgs = Sys.argv in
- if (Array.length cmdArgs < 3 || "-h" = cmdArgs.(1)) then begin
- printUsage() ;
- exit(1)
- end ;
- let a = [| 0 |] in
- let b = [| 1 |] in
- (*
- try begin
- a.(0) <- int_of_string (cmdArgs.(1)) ;
- b.(0) <- int_of_string (cmdArgs.(2)) ;
- end
- with
- | Failure e -> ( begin
- printf "피제수: %s, 제수: %s\n" (cmdArgs.(1)) (cmdArgs.(2));
- printf "숫자 입력에 오류가 있습니다.\n";
- (* exit(1); *)
- end; ) ;
- *)
- a.(0) <- int_of_string (cmdArgs.(1)) ;
- b.(0) <- int_of_string (cmdArgs.(2)) ;
- if a.(0) <= 0 then begin
- printf "피제수: %d\n" a.(0) ;
- printf "피제수는 양의 정수라야 합니다.\n" ;
- exit(1)
- end
- else if b.(0) <= 0 then begin
- printf "제수: %d\n" b.(0) ;
- printf "제수는 양의 정수라야 합니다.\n" ;
- exit(1)
- end ;
- let q = a.(0) / b.(0) in
- let r = a.(0) mod b.(0) in
- printf "나눗셈 %d ÷ %d 의 결과: " a.(0) b.(0) ;
- printf "몫: %d, " q ;
- printf "나머지: %d\n" r ;
- print_newline();
- let k = makeTable a.(0) b.(0) q in
- if k = r then
- printf "\n나머지: %d\n" k ;
- if k = 0 then begin
- printf "%d = %d x %d\n" a.(0) b.(0) q ;
- printf "%d%s %d의 배수(mupltiple)이다.\n" a.(0) (getSuffix a.(0)) b.(0) ;
- printf "%d%s %d의 약수(divisor)이다.\n" b.(0) (getSuffix b.(0)) a.(0)
- end
- else begin
- printf "%d = %d x %d + %d\n" a.(0) b.(0) q r ;
- printf "%d%s %d의 배수(mupltiple)가 아니다.\n" a.(0) (getSuffix a.(0)) b.(0)
- end ;;
- main();;
컴파일> fsc --codepage:949 MakeDivisionTable.fs
실행> MakeDivisionTable.py 500210 61
나눗셈 500210 ÷ 61 의 결과: 몫: 8200, 나머지: 10
8200
________
61 ) 500210
488
------
122
122
------
10
나머지: 10
500210 = 61 x 8200 + 10
500210은 61의 배수(mupltiple)가 아니다.
'프로그래밍 > OCaml' 카테고리의 다른 글
손으로 계산하는 긴자리 곱셈표 만들기 with OCaml (0) | 2013.02.02 |
---|---|
문자열 거꾸로 하기 with OCaml (0) | 2013.02.02 |
OCaml 언어로 큰 정수(big integer) 계산하기 (0) | 2013.01.30 |
7비트 ASCII 코드표 만들기 예제 with OCaml (0) | 2013.01.29 |
OCaml 에 Extlib 설치하고 사용하는 예 (0) | 2013.01.29 |