Created
April 3, 2011 17:40
-
-
Save tormaroe/900601 to your computer and use it in GitHub Desktop.
A test-driven implementation of conversion of numbers to and from SI-prefix in Clojure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns si_prefix.core | |
| (:use clojure.test | |
| clojure.contrib.generic.math-functions)) | |
| (def factors | |
| (zipmap [:y :z :a :f :p :n :u :m :k :M :G :T :P :E :Z :Y] | |
| (map (partial pow 1000) | |
| (filter (complement zero?) | |
| (range -8 9))))) | |
| (with-test | |
| (defn si->num [si] | |
| (let [num (Float. (subs si 0 (dec (count si)))) | |
| prefix (keyword (str (last si)))] | |
| (* num | |
| (prefix factors)))) | |
| (testing "Simple numbers" | |
| (is (approx= (si->num "1y") 0.000000000000000000000001 | |
| 0.000000000000000000000000000000000000001)) | |
| (is (approx= (si->num "1z") 0.000000000000000000001 | |
| 0.000000000000000000000000000000000001)) | |
| (is ( = (si->num "1a") 0.000000000000000001)) | |
| (is ( = (si->num "1f") 0.000000000000001)) | |
| (is ( = (si->num "1p") 0.000000000001)) | |
| (is ( = (si->num "1n") 0.000000001)) | |
| (is ( = (si->num "1u") 0.000001)) | |
| (is ( = (si->num "1m") 0.001)) | |
| (is ( = (si->num "1k") 1000)) | |
| (is ( = (si->num "1M") 1000000)) | |
| (is ( = (si->num "1G") 1000000000)) | |
| (is ( = (si->num "1T") 1000000000000)) | |
| (is ( = (si->num "1P") 1000000000000000)) | |
| (is ( = (si->num "1E") 1000000000000000000)) | |
| (is ( = (si->num "1Z") 1000000000000000000000)) | |
| (is ( = (si->num "1Y") 1000000000000000000000000))) | |
| (testing "Some complex numbers" | |
| (is ( = (si->num "11k") 11000.0)) | |
| (is (approx= (si->num "1.024k") 1024.0 | |
| 0.0001)) | |
| (is ( = (si->num "123.5M") 123500000.0 )) | |
| (is (approx= (si->num "12.2u") 0.0000122 | |
| 0.000000000001)))) | |
| (with-test | |
| (defn num->si [num] | |
| (let [close-num (* num 1.00000000000001) | |
| closest-map (->> factors | |
| (sort-by val) | |
| (filter (fn [x] (< (val x) close-num))) | |
| last) | |
| prefix (name (key closest-map)) | |
| si-adjusted-num (/ num (val closest-map))] | |
| (format "%.0f%s" | |
| si-adjusted-num | |
| prefix))) | |
| (testing "Simple numbers" | |
| (is (= (num->si 1000) "1k")) | |
| (is (= (num->si 1000000) "1M")) | |
| (is (= (num->si 0.000001) "1u")) | |
| (is (= (num->si 0.000000000000001) "1f"))) | |
| (testing "Some complex numbers" | |
| (is (= (num->si 10000) "10k")) | |
| (is (= (num->si 11000000) "11M")) | |
| (is (= (num->si 765432000000000000000000000000) "765432Y")) | |
| (is (= (num->si 0.000000000000000005) "5a")) | |
| (is (= (num->si 0.000000000000000012) "12a")))) | |
| (run-tests) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment