即使当Lat和Distance的值是float值时,下面的Erlang函数有时也会导致daarith错误 可能是什么原因,可以采取什么措施避免它?
-define(EARTH_RADIUS, 6372800).
-define(PI, ct_expand:term(math:pi())).
-define(RAD_FACTOR, ct_expand:term(?PI / 180)).
add_distance_lat(Lat, Distance) ->
Lat + ((Distance / ?EARTH_RADIUS) / ?RAD_FACTOR).
答案 0 :(得分:4)
下面的Erlang函数有时甚至会导致死机错误 当“纬度”和“距离”的值是浮点值时
我不知道ct_expand:term
的作用,但是当给定两个浮点数作为参数时,您可以轻松测试add_distance_lat()
不会引起badarith
错误。我从以下代码中删除了ct_expand:term
:
-module(my).
-compile(export_all).
-define(EARTH_RADIUS, 6372800).
-define(PI, math:pi()).
-define(RAD_FACTOR, ?PI / 180).
test(0) -> ok;
test(N) ->
X = rand:uniform() * 1000,
Y = rand:uniform() * 10000,
io:format("X=~w, Y=~w~n", [X, Y]),
ok = add_distance_lat(X, Y),
test(N-1).
add_distance_lat(Lat, Distance) ->
try Lat + ((Distance / ?EARTH_RADIUS) / ?RAD_FACTOR) of
_GoodResult -> ok
catch
error:Error -> Error;
_:Other -> Other
end.
这是进行10次测试的样子:
5> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
6> my:test(10).
X=169.43178167665917, Y=994.0890019584891
X=106.80009354948483, Y=5318.014760525637
X=483.5152966069006, Y=849.1797017589287
X=413.42192963089917, Y=1813.3077771861872
X=695.5858531252752, Y=6659.873970151745
X=476.4974288029442, Y=3429.9745843747255
X=352.2598626576124, Y=5441.283558914134
X=189.92661305858994, Y=7267.19292963693
X=525.3094754648756, Y=6112.466577043024
X=629.8521203556536, Y=8758.910589712157
ok
在最后一行返回ok的事实意味着add_distance_lat()
的执行没有错误。如果有错误,那么您将在这里得到不匹配项:
ok = add_distance_lat(X, Y),
因为add_distance_lat()
不会返回ok
。这是一个示例:
test() ->
ok = add_distance_lat(12.34567, '10.1111').
add_distance_lat(Lat, Distance) ->
try Lat + ((Distance / ?EARTH_RADIUS) / ?RAD_FACTOR) of
_GoodResult -> ok
catch
error:Error -> Error;
_:Other -> Other
end.
In the shell:
11> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
12> my:test().
** exception error: no match of right hand side value badarith
in function my:test/0 (my.erl, line 15)
该错误表明该行的右侧:
ok = add_distance_lat(12.34567, '10.1111').
是原子badarith
,与原子ok
不匹配。
您可以在第一个test()示例中注释掉io:format()
语句,然后运行该测试100,000,000次。如果返回ok
,则没有badarith
错误:
7> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
8> my:test(100000000).
ok
我非常有信心add_distance_lat()
可以轻松处理浮点数。
另一方面:
3> my:add_distance_lat(30.45, "20.11").
badarith
4> my:add_distance_lat('1000.24', 12.123412341324).
badarith
按照legoscia
的建议,如果在函数中添加is_number()
防护,那么如果您不这样做,则会收到function_clause错误(在评估函数调用时找不到匹配的函数子句) t提供浮点数或整数作为参数:
add_distance_lat(Lat, Distance) when is_number(Lat), is_number(Distance) ->
Lat + ((Distance / ?EARTH_RADIUS) / ?RAD_FACTOR).
在外壳中:
5> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
6> my:add_distance_lat(30.45, "20.11").
** exception error: no function clause matching my:add_distance_lat(30.45,"20.11") (my.erl, line 27)
7> my:add_distance_lat('1000.24', 12.123412341324).
** exception error: no function clause matching my:add_distance_lat('1000.24',12.123412341324) (my.erl, line 27)
如果您的数据没有出现function_clause
错误,请寻找ct_expand:term
来解决问题。