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