컴퓨터 프로그래밍에서 꼭 알아두어야 할 주요 진법은 당연히 10진법, 2진법, 8진법, 16진법이다.
다음은 0 에서 15 까지의 정수를 10진법, 2진법, 8진법, 16진법의 표로 만들어 보여주는 OCaml 소스 코드이다. 진법 변환에 필요한 함수
int = atoi string radix (즉, atoi :: string -> int -> int )
string = itoa number radix (즉, itoa :: int -> int -> string )
를 OCaml 코드로 자체 작성하여 사용하였다.
(아래의 소스는 Python 소스를 F# 소스로 일대일 변환 수정하고, 또 F# 소스를 OCaml 소스로 바꾼 것이라서 명령형 언어 특징을 위주로 작성되어 있다. 그래서 함수형 언어의 관점으로 보면 사이드 이팩트가 많아 난잡하게 보이는 소스이다.)
- (*
- * Filename: makeRadixTable.ml
- * Show the radix table with 10-, 2-, 8-, 16-radices.
- *
- * Execute: ocaml makeRadixTable.ml
- *
- * Or
- *
- * Compile: ocamlc -o makeRadixTable.exe makeRadixTable.ml
- * Execute: makeRadixTable
- *
- * Date: 2013. 1. 29.
- * Author: pkim __AT__scripts.pe.kr
- *)
- exception RuntimeError of string
- exception ValueError of string
- open Printf ;;
- let println s = printf "%s\n" s ;;
- let print s = printf "%s" s ;;
- let printUsage dummy =
- println "Usage: makeRadixTable" ;
- println "Show the radix table with 10-, 2-, 8-, 16-radices." ;;
- let split_char sep str =
- let rec indices acc i =
- try
- let i = succ(String.index_from str i sep) in
- indices (i::acc) i
- with Not_found ->
- (String.length str + 1) :: acc
- in
- let is = indices [0] 0 in
- let rec aux acc = function
- | last::start::tl ->
- let w = String.sub str start (last-start-1) in
- aux (w::acc) (start::tl)
- | _ -> acc
- in
- aux [] is ;;
- let sBASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;;
- let rec sdup str n =
- match n with
- | 0 -> ""
- | k when k > 0 -> str ^ (sdup str (n - 1))
- | _ -> ""
- let contains s1 s2 =
- try
- let len = String.length s2 in
- for i = 0 to (String.length s1) - len do
- if String.sub s1 i len = s2 then raise Exit
- done;
- false
- with Exit -> true ;;
- let join list sep =
- let rec join' list acc =
- match list with
- | [] -> ""
- | [single] -> single
- | one::[two] ->
- if acc = "" then one ^ sep ^ two
- else acc ^ one ^ sep ^ two
- | first::others -> join' others (acc ^ first ^ ", ")
- in
- join' list "" ;;
- let str_reverse str =
let len = String.length str in - let res = String.create len in
- for i = 0 to pred len do
- let j = pred len - i in
- res.[i] <- str.[j]
- done;
- res ;;
- let itoa num radix =
- let isNegative = ref false in
- let num1 = num + 0 in
- let numx = ref num1 in
- if num < 0 then begin
- isNegative := true ;
- numx := (-num)
- end ;
- let nnumx = !numx in
- let q1 = nnumx in
- let q = ref q1 in
- let r = ref 0 in
- let slen = ref 1 in
- while (!q >= radix) do
- r := !q mod radix ;
- q := !q / radix ;
- slen := !slen + 1
- done ;
- let sslen = !slen in
- let str = String.create sslen in
- let p1 = nnumx in
- let p = ref p1 in
- for i = 0 to sslen - 1 do
- r := !p mod radix ;
- p := !p / radix ;
- str.[i] <- sBASE36.[!r]
- done ;
- let str2 = str_reverse str in
- str2;;
- let atoi s radix =
- let ret = ref 0 in
- let isNegative = ref false in
- let len = String.length s in
- let valx = ref 0 in
- let c1 = s.[0] in
- let c = ref c1 in
- if !c = '-' then
- isNegative := true
- else if (!c >= '0' && !c <= '9') then
- ret := (int_of_char !c) - (int_of_char '0')
- else if (!c >= 'A' && !c <= 'Z') then
- ret := (int_of_char !c) - (int_of_char 'A') + 10
- else if (!c >= 'a' && !c <= 'z') then
- ret := (int_of_char !c) - (int_of_char 'a') + 10 ;
- if (!ret >= radix) then
- raise (ValueError (sprintf "Can not read \"%s\" (as radix %d): '%c' is invalid." s radix !c ) ) ;
- for i = 1 to len - 1 do
- c := s.[i] ;
- ret := (!ret)*radix ;
- if (!c >= '0' && !c <= '9') then
- valx := int_of_char !c - int_of_char '0'
- else if (!c >= 'A' && !c <= 'Z') then
- valx := int_of_char !c - int_of_char 'A' + 10
- else if (!c >= 'a' && !c <= 'z') then
- valx := int_of_char !c - int_of_char 'a' + 10 ;
- if (!valx >= radix) then
raise (ValueError (sprintf "Can not read \"%s\" (as radix %d): '%c' is invalid." s radix !c ) ) ; - ret := (!ret) + (!valx)
- done;
- if (!isNegative) then
- ret := (-(!ret) ) ;
- !ret ;;
- let makeTable() =
- let sbuf = "" in
- let sbuf = sbuf ^ (sdup "+-------" 4) in
- let sbuf = sbuf ^ "+" in
- println sbuf ;
- let sbuf = "| Dec" in
- let sbuf = sbuf ^ "\t| Bin" in
- let sbuf = sbuf ^ "\t| Oct" in
- let sbuf = sbuf ^ "\t| Hex |" in
- println sbuf ;
- let sbuf = "" in
- let sbuf = sbuf ^ (sdup "+-------" 4) in
- let sbuf = sbuf ^ "+" in
- println sbuf ;
- for i = 0 to (16-1) do
- let sbuf = sprintf "| %2d" i in
- let abuf = itoa i 2 in
- let tbuf = sprintf "\t| %4s" abuf in
- let sbuf = sbuf ^ tbuf in
- let abuf = itoa i 8 in
- let tbuf = sprintf "\t| %2s" abuf in
- let sbuf = sbuf ^ tbuf in
- let abuf = itoa i 16 in
- let tbuf = sprintf "\t| %-2s |" abuf in
- let sbuf = sbuf ^ tbuf in
- println sbuf
- done ;
- let sbuf = "" in
- let sbuf = sbuf ^ (sdup "+-------" 4) in
- let sbuf = sbuf ^ "+" in
- println sbuf ;
- "" ;;
- let main() =
- let cmdArgs = Sys.argv in
- if (Array.length cmdArgs > 1 && "-h" = cmdArgs.(1)) then begin
- printUsage() ;
- exit(1)
- end ;
- makeTable() ;;
- main()
실행 결과:
'프로그래밍 > OCaml' 카테고리의 다른 글
7비트 ASCII 코드표 만들기 예제 with OCaml (0) | 2013.01.29 |
---|---|
OCaml 에 Extlib 설치하고 사용하는 예 (0) | 2013.01.29 |
대화형 모드의 진법(radix) 변환 예제 with OCaml (0) | 2013.01.27 |
황금비율(golden ratio) 구하기 with OCaml (0) | 2013.01.27 |
현재 시각 알아내기 for OCaml (0) | 2013.01.27 |