﻿ 浮点 – Enum.Sum和我的自定义和函数之间的Elixir意外浮点结果差异 - 代码日志

#### 浮点 – Enum.Sum和我的自定义和函数之间的Elixir意外浮点结果差异

``````defmodule Homework do
@spec sum(list(number())) :: number()
def sum(l) do
case l do
[] -> 0
[a | as] -> a + sum(as)
end
end
end
``````

``````[-2, -2.1524700989447303, 1] |> fn(l) -> Enum.sum(l) === Homework.sum(l) end.()
``````

``````iex(1)> [-2, -2.1524700989447303, 1] |> Enum.sum
-3.1524700989447307
iex(2)> [-2, -2.1524700989447303, 1] |> Homework.sum
-3.1524700989447303
``````

https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/enum.ex

``````@spec sum(t) :: number
def sum(enumerable) do
reduce(enumerable, 0, &+/2)
end

@spec reduce(t, any, (element, any -> any)) :: any
def reduce(enumerable, acc, fun) when is_list(enumerable) do
:lists.foldl(fun, acc, enumerable)
end
``````

https://github.com/erlang/otp/blob/master/lib/stdlib/src/lists.erl

``````-spec foldl(Fun, Acc0, List) -> Acc1 when
Fun :: fun((Elem :: T, AccIn) -> AccOut),
Acc0 :: term(),
Acc1 :: term(),
AccIn :: term(),
AccOut :: term(),
List :: [T],
T :: term().

foldl(F, Accu, [Hd|Tail]) ->
foldl(F, F(Hd, Accu), Tail); %% here!
foldl(F, Accu, []) when is_function(F, 2) -> Accu.
``````

@Sneftel的评论让我做了以下实验：

``````@spec sum(list(number())) :: number()
def sum(l) do
case Enum.reverse(l) do # reversing first
[] -> 0
[a | as] -> a + sum(as)
end
end
``````

``````iex(1)> Homework.sum([-2, -2.1524700989447303, 1])
-3.1524700989447307
iex(2)> Enum.sum([-2, -2.1524700989447303, 1])
-3.1524700989447307
``````

``````def sum(l) do
case l do
[] -> 0
[a | as] -> sum(as) + a
end
end

iex(1)> Homework.sum([-2, -2.1524700989447303, 1])
-3.1524700989447303
iex(2)> Enum.sum([-2, -2.1524700989447303, 1])
-3.1524700989447307
``````