Ecto returns 科学(指数)记数法中的数字

Ecto returns numbers in scientific (exponential) notation

我不知道这是 Ecto 还是 Elixir 的问题。当我在数据库中有一个数字,如 1000、15000 等时。Ecto returns 为 1.0e3、1.5e4... 如果我将 1000 更改为 1234,一切正常。

Elixir 1.3.2,Ecto 2.0.3,MySQL

迁移:

alter table(:incoming_transfers) do
  add :fee, :float # Ecto translates it as DOUBLE in MySQL
end

架构:

schema "incoming_transfers" do
  field :fee, :float
end

如果我在数据库中手动将 DOUBLE 类型更改为 FLOAT,问题仍然存在。但是如果我把它改成INTEGER就好了。

Elixir 对 Float just delegates to :io_lib_format.fwrite_g/1 and :io_lib_format.fwrite_g/1's source in Erlang/OTPInspect 实现提到它试图以尽可能少的字符数准确打印数字。因此,1000 被转换为 1.0e3,因为它比 1000.0 短,但 100.0 没有被转换为 1.0e2,因为它不比 100.0 短.类似地,12300.0 被转换为 1.23e4,因为它更短。

%%  Writes the shortest, correctly rounded string that converts
%%  to Float when read back with list_to_float/1.
%%
%%  See also "Printing Floating-Point Numbers Quickly and Accurately"
%%  in Proceedings of the SIGPLAN '96 Conference on Programming
%%  Language Design and Implementation.

二郎:

1> [1000.0, 100.0, 12300.0].
[1.0e3,100.0,1.23e4]

请注意,这 不会 导致失去任何准确性(超出浮点数已经失去的范围)。 1000.0 正好等于 1.0e3.

对于那些想要覆盖@Dogbert 提到的功能的人。只需将其放入您的代码中即可:

defimpl Inspect, for: Float do
  def inspect(term, _opts) do
    IO.iodata_to_binary(:io_lib_format.fwrite_g(term))
  end
end

并将 :io_lib_format.fwrite_g(term) 更改为 :erlang. float_to_binary(term, [decimals: 6]) 之类的内容。 例如,对于 7.12 它 returns "7.120000".

无论如何,我认为使用 Decimal 代替 Float 会更好。