I found there’s no builtin infinity, negative infinity and NaN in Elixir/Erlang. How do you solve this problem? I know I can use :infinity
so that I can compare it and all numbers, but how about negative infinity and NaN?
There is neither. Even :infinity
does only work by accident (term ordering).
@tony612: as @NobbZ said there are no equivalents.
If you really need to have them then you need a small hack.
From Basic operators you can read about term ordering:
The reason we can compare different data types is pragmatism. Sorting algorithms don’t need to worry about different data types in order to sort. The overall sorting order is defined below:
number < atom < reference < function < port < pid < tuple < map < list < bitstring
Therefore you could use a hack like this one:
negative_infinity = {}
number = {0}
infinity = {:infinity}
negative_infinity < number
# true
number < infinity
# true
I’m not sure, but I think that comparing numbers should be faster than comparing them in tuples, so personally I don’t recommend them. At least for me comparing tuples is less clear.
The Elixir-way is to pattern-match them:
defmodule MyComparator do
def compare(:infinity, :negative_infinity), do: :gt
def compare(:infinity, number) when is_number(number), do: :gt
def compare(:negative_infinity, :infinity), do: :lt
def compare(:negative_infinity, number) when is_number(number), do: :lt
def compare(number, :infinity) when is_number(number), do: :lt
def compare(number, :negative_infinity) when is_number(number), do: :gt
# def eq ...
# def ge ...
# def gt ...
# def le ...
# def lg ...
# def ne ...
end
Similarly for NaN. In JavaScript
expression: 0 / 0
returns NaN
, but Elixir raises ArithmeticError
.
From here you have two ways:
try/rescue
- use this only you don’t have any other waypattern matching
- really recommend - it’s 100% Elixir-way
defmodule MyMath do
def safe_div(_dividend, 0), do: {:error, :dividing_by_zero}
def safe_div(dividend, divider), do: {:ok, dividend / divider}
end
# first_num = ...
# second_num = ...
case MyMath.safe_div(first_num, second_num) do
{:ok, _result} -> IO.puts "Yeah!"
{:error, _error} -> IO.puts "Oops!"
end
Is it what you are looking for?