Skip to content

Instantly share code, notes, and snippets.

@rlei
Created December 1, 2015 07:28
Show Gist options
  • Save rlei/c3dedc651e19c5f78df6 to your computer and use it in GitHub Desktop.
Save rlei/c3dedc651e19c5f78df6 to your computer and use it in GitHub Desktop.
Convert number to its Chinese representation
; Algorithm described in http://zhuanlan.zhihu.com/iobject/20370983
; Be warned: it's in Chinese too ;)
(def digits-name (zipmap "0123456789" "零一二三四五六七八九"))
(def tens-name (zipmap [1 2 3] [\十 \百 \千]))
(defn digit-pos-to-name [pos]
(cond (= pos 0) nil
(= 0 (rem pos 8)) \亿
(= 0 (rem pos 4)) \万
:else (tens-name (rem pos 4))))
(def unit-rank (zipmap [nil \十 \百 \千 \万 \亿] (range 6)))
(defn append-digit [[results pending-zero last-unit] tuple]
(let [digit (first tuple)
this-unit (second tuple)
this-str (digits-name digit)]
(if (= digit \0)
(if (> (unit-rank last-unit) (unit-rank this-unit))
[results true last-unit]
[(conj results this-unit) false this-unit])
[(conj results (if pending-zero \零) this-str this-unit)
false this-unit])))
(defn to-chinese-num-full [n]
(apply str (first (reduce append-digit [[] false nil]
(reverse (map-indexed #(list %2 (digit-pos-to-name %1))
(reverse (str n))))))))
(to-chinese-num-full 1004000007000500)
;=> "一千零四万亿零七百万零五百"
(to-chinese-num-full 123000520)
;=> "一亿二千三百万零五百二十"
(to-chinese-num-full 1234070000123780000087006786520988800000)
;=> "一千二百三十四万零七百亿零一十二万三千七百八十亿零八千七百亿六千七百八十六万五千二百零九亿八千八百八十万"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment