Jakub Zawiślak
Jakub Zawiślak

Reputation: 5512

Ecto returns numbers in scientific (exponential) notation

I don't know if it's an Ecto's or Elixir's issue. When I have a number in database like 1000, 15000 etc. Ecto returns it as 1.0e3, 1.5e4... If I change that 1000 to 1234 everything is ok.

Elixir 1.3.2, Ecto 2.0.3, MySQL

Migration:

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

Schema:

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

If I change manually in my database type DOUBLE to FLOAT the problem remains. But if I change it to INTEGER, it's good.

Upvotes: 2

Views: 1089

Answers (2)

Jakub Zawiślak
Jakub Zawiślak

Reputation: 5512

For those who want to override function mentioned by @Dogbert. Just put it in your code:

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

and change :io_lib_format.fwrite_g(term) to something like :erlang. float_to_binary(term, [decimals: 6]). For example, for 7.12 it returns "7.120000".

Anyway, I think it would be better to use Decimal instead of Float.

Upvotes: 2

Dogbert
Dogbert

Reputation: 222358

Elixir's Inspect implementation for Float just delegates to :io_lib_format.fwrite_g/1 and :io_lib_format.fwrite_g/1's source in Erlang/OTP mentions that it tries to print the number accurately in the least number of characters possible. So, 1000 is converted to 1.0e3 because that's shorter than 1000.0, but 100.0 is not converted to 1.0e2 because that's not shorter than 100.0. Similarly 12300.0 is converted to 1.23e4 because that's shorter.

%%  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.

Erlang:

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

Note that this does not result in losing any accuracy (beyond what floating numbers already lose). 1000.0 is exactly equal to 1.0e3.

Upvotes: 2

Related Questions