Floating point 如何在Erlang中检查浮点是否为整数?
我正在学习Erlang,作为在反向波兰符号计算器中实现阶乘函数的练习。到目前为止,我有:Floating point 如何在Erlang中检查浮点是否为整数?,floating-point,integer,erlang,Floating Point,Integer,Erlang,我正在学习Erlang,作为在反向波兰符号计算器中实现阶乘函数的练习。到目前为止,我有: -module(rps). -export([calculate/1]). calculate(List) -> calculate(List, []). calculate([], [ Number ]) -> Number; calculate([ Head | Tail ], Stack) -> case Head of "+" -> [ B
-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).
现在问题出在我的阶乘/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
中有一个案例,可以检测出这样的数字并将它们转换成整数,但也许有更好的方法?存在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 ]).
经过深思熟虑,以下是我自己的看法:
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\u to\u integer
的帮助程序,它返回一个整数作为任何整数,否则会抛出一个错误。这个名字有点误导人,因为它也可以处理整数。然后我用它来保护factorial/1,如果你使用区域整数,那么你可以使用相应的运算,在这个例子中是-div。所以“/”->[B,A | Rest]=Stack,calculate(Tail,[A div B | Rest])代码>。谢谢。这可能是解决方案的一部分,但问题是它总是会截断结果。我确实希望在一般情况下支持浮动,对于分数,我希望我的阶乘抛出。我只想要3.0
生成6
。谢谢。我做了一个小编辑,因为您的原始代码导致编译错误(rpcalc.erl:20:变量“a”是未绑定的rpcalc.erl:20:变量“B”是未绑定的错误
)。此外,在某些情况下,它确实有助于防止除法产生的浮动,但是`rpcalc:calculate([2.0,2,“+”,“!”])又如何呢?@TadeuszŁazurski,只需添加几个条件。例如“/”->[B,A | Rest]=堆栈,如果是|整数(A),则是|整数(B),A rem B=:=0->计算(Tail[A div B | Rest]);A==trunc(A),B==trunc(B)->计算(Tail[trunc(A)div trunc(B)| Rest]);真->计算(尾,[A/B | Rest])结束代码>@Atomic_alarm我认为试图阻止除法返回浮动不是最好的方法。如果我增加更多的操作,我也必须保护它们。此外,浮动可能来自calculate/1
的原始输入。请看一看我自己的答案,让我知道你的想法。@TadeuszŁazurski:这个错误是由你的代码的非爱尔兰性质引起的。请看我的更正。这是惯用的Erlang。@TadeuszŁazurski非整数有阶乘函数。它们是Gamma函数和Pi函数。好的解决方案,但最好使用模式匹配和比较。结果float\u to\u integer(N),当是\u integer(N)->N时;float_to_integer(N)->integer=trunc(N),案例N==true的整数->整数;false->error(badarg)end.
Btw,如果您需要检查代码是否有效,您可以在上提问。谢谢@Atomic_alarm。我已经根据您的建议更新了代码示例。