如何在Erlang中检查浮点数是否为整数?

时间:2017-01-22 09:21:32

标签: floating-point integer erlang

我从Learn You Some Erlang for great good!学习Erlang,并尝试在反向波兰表示法计算器中实现阶乘函数。到目前为止,我有这个:

-module(rps).
-export([calculate/1]).

calculate(List) ->
  calculate(List, []).

calculate([], [ Number ]) ->
  Number;
calculate([ Head | Tail ], Stack) ->
  case Head of
    "+" ->
      [ B, A | Rest ] = Stack,
      calculate(Tail, [ A + B | Rest ]);
    "-" ->
      [ B, A | Rest ] = Stack,
      calculate(Tail, [ A - B | Rest ]);
    "*" ->
      [ B, A | Rest ] = Stack,
      calculate(Tail, [ A * B | Rest ]);
    "/" ->
      [ B, A | Rest ] = Stack,
      calculate(Tail, [ A / B | Rest ]);
    "!" ->
      [ A | Rest ] = Stack,
      calculate(Tail, [ factorial(A) | Rest ]);
    _ ->
      calculate(Tail, [ Head | Stack ])
  end.

factorial(N) ->
  factorial(N, 1).

factorial(0, Accumulator) ->
  Accumulator;
factorial(N, Accumulator) when N >= 0  ->
  factorial(N - 1, Accumulator * N).

现在问题在于我的factorial / 2函数,特别是N = 0的基本情况。只要堆栈上的第一个元素是整数,它就可以正常工作,例如:

5> rpcalc:calculate([1, 2, "+", "!"]).
6

但是我注意到除非两个参数都是整数,结果是一个整数,所以除非总是返回一个浮点数,例如:

7> 4 / 2.
2.0

所以有时浮标出现在我的堆栈上。然后,即使它们是正数和整数,我的因子也会失败,如0.0 =/= 0。效果是:

13> rpcalc:calculate([6, 2, "/", "!"]).
** exception error: no function clause matching rpcalc:factorial(-1.0,0.0) (rpcalc.erl, line 33)
     in function  rpcalc:calculate/2 (rpcalc.erl, line 25)

在这里支持积极的整体花车最优雅的方式是什么?我的直觉是在factorial/1中有一个案例可以检测到这些数字并将它们转换为整数,但也许有更好的方法?

2 个答案:

答案 0 :(得分:1)

存在div,它采用整数并执行整数除法。你可以把它写成:

calculate([], [ Number ]) ->
    Number;
calculate([ "+" | Tail ], [ B, A | Rest ]) ->
    calculate(Tail, [ A + B | Rest ]);
calculate([ "-" | Tail ], [ B, A | Rest ]) ->
    calculate(Tail, [ A - B | Rest ]);
calculate([ "*" | Tail ], [ B, A | Rest ]) ->
    calculate(Tail, [ A * B | Rest ]);
calculate([ "/" | Tail ], [ B, A | Rest ])
    when is_integer(A), is_integer(B), A rem B =:= 0 ->
    calculate(Tail, [ A div B | Rest ]);
calculate([ "/" | Tail ], [ B, A | Rest ]) ->
    calculate(Tail, [ A / B | Rest ]);
calculate([ "!" | Tail ], [ A | Rest ]) ->
    calculate(Tail, [ factorial(A) | Rest ]);
calculate([ Head | Tail ], Stack) ->
    calculate(Tail, [ Head | Stack ]).

答案 1 :(得分:1)

经过一番思考之后,我自己对此有所了解:

factorial(N) ->
  factorial(float_to_integer(N), 1).

factorial(0, Accumulator) ->
  Accumulator;
factorial(N, Accumulator) when N >= 0  ->
  factorial(N - 1, Accumulator * N).

float_to_integer(N) when is_integer(N) ->
  N;
float_to_integer(N) when is_float(N) ->
  Integer = trunc(N),
  case N == Integer of
    true ->
      Integer;
    false ->
      error(badarg)
  end.

我添加了一个名为float_to_integer的帮助程序,它为任何整数返回一个整数,否则会抛出错误。这个名称有点误导,因为它也可以处理整数。然后我用它来后卫 factorial/1