Erlang里数字格式化的问题,常用的取整方法都很简单BIF也很方便,对于保留几位小数的需求,做起来就相当复杂。
如果用BIF实现,就是类似如下的代码了
list_to_float(hd(io_lib:format(Format, Number))). |
在SHELL里执行下是这样的
Erlang R14A (erts-5.8) [source] [64-bit] [smp:8:8] [rq:8] [async-threads:0] [hipe] [kernel-poll:false] |
Eshell V5.8 (abort with ^G) |
1> F = fun(Format, Number) -> list_to_float(hd(io_lib:format(Format, [Number]))) end. |
#Fun<erl_eval.12.113037538> |
看上去实现目标了,可转念想想效率问题就会觉得值得商榷。先不说io_lib:format内做了多少工作,多次类型转换是不可避免了。在大量计算时这个效率还是需要关注的。
那么有没有更好的办法呢?
先看代码:
简单的做了一个测试,对比两种算法的性能,测试过程如下
Erlang R14A (erts-5.8) [source] [64-bit] [smp:8:8] [rq:8] [async-threads:0] [hipe] [kernel-poll:false] |
Eshell V5.8 (abort with ^G) |
1> F = fun(Format, Number) -> list_to_float(hd(io_lib:format(Format, [Number]))) end. |
#Fun<erl_eval.12.113037538> |
2> F2 = fun(Number, X) -> N = math:pow(10,X), round(Number*N)/N end. |
#Fun<erl_eval.12.113037538> |
3> io:format("~p~n",[now()]), lists:foreach(fun(_I)-> F2(8.22986,3) end, lists:seq(1,1000000)), io:format("~p~n",[now()]). |
4> io:format("~p~n",[now()]), lists:foreach(fun(_I)-> F2(8.22986,3) end, lists:seq(1,1000000)), io:format("~p~n",[now()]). |
5> io:format("~p~n",[now()]), lists:foreach(fun(_I)-> F2(8.22986,3) end, lists:seq(1,1000000)), io:format("~p~n",[now()]). |
6> io:format("~p~n",[now()]), lists:foreach(fun(_I)-> F2(8.22986,3) end, lists:seq(1,1000000)), io:format("~p~n",[now()]). |
7> io:format("~p~n",[now()]), lists:foreach(fun(_I)-> F("~.3f", 8.22986) end, lists:seq(1,1000000)), io:format("~p~n",[now()]). |
8> io:format("~p~n",[now()]), lists:foreach(fun(_I)-> F("~.3f", 8.22986) end, lists:seq(1,1000000)), io:format("~p~n",[now()]). |
9> io:format("~p~n",[now()]), lists:foreach(fun(_I)-> F("~.3f", 8.22986) end, lists:seq(1,1000000)), io:format("~p~n",[now()]). |
做100w次计算可以看出,io_lib方法需要27~28秒钟,自己写的算法需要19~20秒钟,同时我观察了CPU的使用情况,自己写的算法会低10%左右的消耗,推荐适时DIY