Non-decimal radices/Convert: Difference between revisions

Content added Content deleted
(→‎{{header|Quackery}}: rewrote to match task requirements)
(support 0, fix non-exhaustive matching, use modern API)
Line 2,524: Line 2,524:
- : int = 26
- : int = 26


A real base conversion example: {{trans|Haskell}}
A real base conversion implementation:
<syntaxhighlight lang="ocaml">let basen_of_int b n : string =
let tab = "0123456789abcdefghijklmnopqrstuvwxyz" in
let rec aux x l =
if x < b
then tab.[x] :: l
else aux (x / b) (tab.[x mod b] :: l)
in
String.of_seq (List.to_seq (aux n []))


let basen_to_int b ds : int =
<syntaxhighlight lang="ocaml">let to_base b v =
let rec to_base' a v =
let of_sym c =
if v = 0 then
int_of_char c - match c with
| '0' .. '9' -> int_of_char '0'
a
| 'a' .. 'z' -> int_of_char 'a' - 10
else
to_base' (v mod b :: a) (v / b)
| 'A' .. 'Z' -> int_of_char 'A' - 10
| _ -> invalid_arg "unkown digit"
in
in
String.fold_left (fun n d -> n * b + of_sym d) 0 ds</syntaxhighlight>
to_base' [] v

let from_base b ds =
List.fold_left (fun n k -> n * b + k) 0 ds

let to_alpha_digit n =
if n < 10 then
char_of_int (n + int_of_char '0')
else
char_of_int (n + int_of_char 'a' - 10)

let to_alpha_digits ds =
let buf = Buffer.create (List.length ds) in
List.iter (fun i -> Buffer.add_char buf (to_alpha_digit i)) ds;
Buffer.contents buf

let from_alpha_digit c = match c with
'0'..'9' -> int_of_char c - int_of_char '0'
| 'A'..'Z' -> int_of_char c - int_of_char 'A' + 10
| 'a'..'z' -> int_of_char c - int_of_char 'a' + 10

let from_alpha_digits s =
let result = ref [] in
String.iter (fun c -> result := from_alpha_digit c :: !result) s;
List.rev !result</syntaxhighlight>


Example:
Example:

<pre>
<pre>
# to_alpha_digits (to_base 16 42);;
# basen_of_int 16 26;;
- : string = "2a"
- : string = "1a"
# from_base 16 (from_alpha_digits "2a");;
# basen_to_int 16 "1a";;
- : int = 42
- : int = 26
</pre>
</pre>