Erlang-Badarith错误

Erlang-Badarith错误,erlang,Erlang,以下Erlang函数有时会导致badarith错误,即使Lat和Distance的值是浮点值 原因是什么?可以采取什么措施来避免 -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 / ?EAR

以下Erlang函数有时会导致badarith错误,即使Lat和Distance的值是浮点值 原因是什么?可以采取什么措施来避免

-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).
下面的Erlang函数有时甚至会导致badarith错误 当Lat和距离的值为浮动值时

我不知道
ct\u expand:term
的作用是什么,但您可以很容易地测试
add\u distance\u lat()
在给定两个浮点数作为参数时不会导致
badarith
错误。我从以下代码中删除了
ct\u 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\u distance\u lat()
时没有错误。如果出现错误,则您将在此处得到错误匹配:

ok = add_distance_lat(X, Y),
因为
add\u distance\u 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').
是atom
badarith
,它与atom
ok
不匹配

您可以注释掉第一个test()示例中的
io:format()
语句,然后运行100000000次测试。如果返回了
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\u distance\u lat()
可以从容地处理浮动

另一方面:

3> my:add_distance_lat(30.45, "20.11").
badarith

4> my:add_distance_lat('1000.24', 12.123412341324).
badarith
正如
legosca
所建议的,如果在函数中添加
is_number()
保护,那么如果不提供浮点或整数作为参数,则会出现函数_子句错误(在计算函数调用时找不到匹配的函数子句):

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\u子句
错误,请查看
ct\u expand:term

下面的Erlang函数有时甚至会导致badarith错误 当Lat和距离的值为浮动值时

我不知道
ct\u expand:term
的作用是什么,但您可以很容易地测试
add\u distance\u lat()
在给定两个浮点数作为参数时不会导致
badarith
错误。我从以下代码中删除了
ct\u 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\u distance\u lat()
时没有错误。如果出现错误,则您将在此处得到错误匹配:

ok = add_distance_lat(X, Y),
因为
add\u distance\u 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').
是atom
badarith
,它与atom
ok
不匹配

您可以注释掉第一个test()示例中的
io:format()
语句,然后运行100000000次测试。如果返回了
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\u distance\u lat()
可以从容地处理浮动

另一方面:

3> my:add_distance_lat(30.45, "20.11").
badarith

4> my:add_distance_lat('1000.24', 12.123412341324).
badarith
正如
legosca
所建议的,如果在函数中添加
is_number()
保护,那么如果不提供浮点或整数作为参数,则会出现函数_子句错误(在计算函数调用时找不到匹配的函数子句):

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\u子句
错误,请查看
ct\u expand:term
以了解问题。

您能否回答问题并添加完整的
badarith
错误?它可能包含更多的线索。对于这样的函数,我会添加防护:
add_distance_lat(lat,distance)when is_number(lat),is_number(distance)->
以便更早地捕获错误。感谢@legocia的防护思想。您能提出问题并添加完整的
badarith
错误吗?它可能包含更多的线索。对于这样的函数,我会添加防护:
add_distance_lat(lat,distance)when is_number(lat),is_number(distance)->
,以便更早地捕捉错误。感谢@legocia的防护思想。