Packages
krug
1.1.21
2.0.36
2.0.35
2.0.34
2.0.33
2.0.32
2.0.31
2.0.30
2.0.29
2.0.27
2.0.26
2.0.25
2.0.24
2.0.23
2.0.22
2.0.20
2.0.19
2.0.18
2.0.17
2.0.16
2.0.15
2.0.14
2.0.13
2.0.12
2.0.11
2.0.10
2.0.9
2.0.8
2.0.7
2.0.6
2.0.5
2.0.4
2.0.1
2.0.0
1.1.53
1.1.52
1.1.50
1.1.49
1.1.48
1.1.47
1.1.46
1.1.45
1.1.44
1.1.43
1.1.42
1.1.41
1.1.40
1.1.39
1.1.38
1.1.37
1.1.36
1.1.35
1.1.34
1.1.33
1.1.32
1.1.31
1.1.30
1.1.29
1.1.28
1.1.27
1.1.26
1.1.25
1.1.24
1.1.23
1.1.22
1.1.21
1.1.20
1.1.19
1.1.18
1.1.17
1.1.16
1.1.15
1.1.14
1.1.12
1.1.10
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.9
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.31
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.0
A Utilitary package functionalities modules for improve a secure performatic development.
Current section
Files
Jump to
Current section
Files
lib/krug/util/number.util.ex
defmodule Krug.NumberUtil do
@moduledoc """
Utilitary safe module for some numeric (non Math) operations/transformations.
"""
alias Krug.StringUtil
@numerals ["0","1","2","3","4","5","6","7","8","9"]
@float_chars ["-",".",",","0","1","2","3","4","5","6","7","8","9"]
@positive_float_chars [".",",","0","1","2","3","4","5","6","7","8","9"]
@numeric_specials ["-",".",","]
@numeric_specials_invalid ["-.","-,",".-",",-","--","..",".,",",.",",,"]
@doc """
Return the max integer value.
Useful for validations for database int(11) columns for example.
## Example
```elixir
iex > Krug.NumberUtil.max_integer()
4294967295
```
"""
def max_integer() do
4294967295
end
@doc """
Return if a value cannot be converted to a number.
## Example
```elixir
iex > Krug.NumberUtil.is_nan(10)
false
```
```elixir
iex > Krug.NumberUtil.is_nan("10")
false
```
```elixir
iex > Krug.NumberUtil.is_nan("-1.0")
false
```
```elixir
iex > Krug.NumberUtil.is_nan("-1,0")
false
```
```elixir
iex > Krug.NumberUtil.is_nan("10A")
true
```
```elixir
iex > Krug.NumberUtil.is_nan("-1-1")
true
```
```elixir
iex > Krug.NumberUtil.is_nan("1-1")
true
```
```elixir
iex > Krug.NumberUtil.is_nan(".5")
true
```
```elixir
iex > Krug.NumberUtil.is_nan("-.5")
true
```
```elixir
iex > Krug.NumberUtil.is_nan(",5")
true
```
```elixir
iex > Krug.NumberUtil.is_nan("-,5")
true
```
"""
def is_nan(number) do
cond do
(is_number(number)) -> false
true -> is_nan2(number)
end
end
@doc """
Convert any number or string that could be converted in a number to
a positive float number.
If the ```number``` received its not a number/cannot be converted to one,
then return ```0.0```.
## Examples
```elixir
iex > Krug.NumberUtil.to_positive(-10)
10
```
```elixir
iex > Krug.NumberUtil.to_positive("-10,5")
10.5
```
```elixir
iex > Krug.NumberUtil.to_positive("-10.5")
10.5
```
```elixir
iex > Krug.NumberUtil.to_positive("-10,5A")
0.0
```
```elixir
iex > Krug.NumberUtil.to_positive("-1-0,5")
0.0
```
```elixir
iex > Krug.NumberUtil.to_positive("1-0,5")
0.0
```
```elixir
iex > Krug.NumberUtil.to_positive("1.0.5")
10.5
```
```elixir
iex > Krug.NumberUtil.to_positive("1,0,5")
10.5
```
```elixir
iex > Krug.NumberUtil.to_positive("1.0,5")
10.5
```
```elixir
iex > Krug.NumberUtil.to_positive("1,0.5")
10.5
```
```elixir
iex > Krug.NumberUtil.to_positive("-1,0,5")
10.5
```
"""
def to_positive(number) do
cond do
(is_number(number)) -> number |> to_positive2()
true -> number |> to_float() |> to_positive2()
end
end
@doc """
Return an integer value if a value received can be converted to a number.
Otherwise return 0.
## Examples
```elixir
iex > Krug.NumberUtil.to_integer(nil)
0
```
```elixir
iex > Krug.NumberUtil.to_integer("")
0
```
```elixir
iex > Krug.NumberUtil.to_integer("1,,2")
0
```
```elixir
iex > Krug.NumberUtil.to_integer("1-2")
0
```
```elixir
iex > Krug.NumberUtil.to_integer("-1..2")
0
```
```elixir
iex > Krug.NumberUtil.to_integer("1A")
0
```
```elixir
iex > Krug.NumberUtil.to_integer(-1.2)
-1
```
```elixir
iex > Krug.NumberUtil.to_integer("-1.2")
-1
```
```elixir
iex > Krug.NumberUtil.to_integer("-1,2")
-1
```
```elixir
iex > Krug.NumberUtil.to_integer("1.2")
1
```
```elixir
iex > Krug.NumberUtil.to_integer("1,2")
1
```
"""
def to_integer(number) do
cond do
(is_integer(number)) -> number
(is_float(number)) -> number |> round()
true -> number |> StringUtil.trim() |> to_integer2()
end
end
@doc """
Return a float value if a value received can be converted to a number.
Otherwise return 0.
## Examples
```elixir
iex > Krug.NumberUtil.to_float(nil)
0.0
```
```elixir
iex > Krug.NumberUtil.to_float("")
0.0
```
```elixir
iex > Krug.NumberUtil.to_float("1,,2")
0.0
```
```elixir
iex > Krug.NumberUtil.to_float("1-2")
0.0
```
```elixir
iex > Krug.NumberUtil.to_float("-1..2")
0.0
```
```elixir
iex > Krug.NumberUtil.to_float("1A")
0.0
```
```elixir
iex > Krug.NumberUtil.to_float(-1.2)
-1.2
```
```elixir
iex > Krug.NumberUtil.to_float("-1.2")
-1.2
```
```elixir
iex > Krug.NumberUtil.to_float("-1,2")
-1.2
```
```elixir
iex > Krug.NumberUtil.to_float("1.2")
1.2
```
```elixir
iex > Krug.NumberUtil.to_float("1,2")
1.2
```
```elixir
iex > Krug.NumberUtil.to_float("1.2,4")
12.4
```
```elixir
iex > Krug.NumberUtil.to_float("1,2,4")
12.4
```
```elixir
iex > Krug.NumberUtil.to_float("-1,2.4")
-12.4
```
"""
def to_float(number) do
cond do
(is_float(number)) -> number
(is_integer(number)) -> number
(is_nan(number)) -> 0.0
true -> convert_to_float(number)
end
end
@doc """
Applies ```to_float()``` to a received value, then format with
```decimals``` decimal digits, using ```,``` (default) or ```.```.
## Examples
```elixir
iex > Krug.NumberUtil.to_float_format(nil,2)
0,00
```
```elixir
iex > Krug.NumberUtil.to_float_format("1A",2)
0,00
```
```elixir
iex > Krug.NumberUtil.to_float_format("1,2",2)
1,20
```
```elixir
iex > Krug.NumberUtil.to_float_format("1,2",5)
1,20000
```
```elixir
iex > Krug.NumberUtil.to_float_format(nil,2,false)
0.00
```
```elixir
iex > Krug.NumberUtil.to_float_format("1A",2,false)
0.00
```
```elixir
iex > Krug.NumberUtil.to_float_format("1,2",2,false)
1.20
```
```elixir
iex > Krug.NumberUtil.to_float_format("1,2",5,false)
1.20000
```
"""
def to_float_format(number,decimals,comma_as_decimal_separator \\ true) do
number = number |> to_float()
number_array = :io_lib.format("~.#{decimals}f",[number]) |> StringUtil.split(".")
cond do
(nil == decimals or !(decimals > 0)) -> number_array |> hd()
true -> to_float_format2(number_array,decimals,comma_as_decimal_separator)
end
end
@doc """
Verify if a value received is a valid number. If is valid return the
value received passing by ```to_integer()``` or ```toFloat```.
Otherwise return the ```value_if_empty_or_nil``` parameter value.
Useful to forces a default value, to validations for example.
## Examples
```elixir
iex > Krug.NumberUtil.coalesce(nil,1)
1
```
```elixir
iex > Krug.NumberUtil.coalesce("",1)
1
```
```elixir
iex > Krug.NumberUtil.coalesce(" ",1)
1
```
```elixir
iex > Krug.NumberUtil.coalesce("1-1",1)
1
```
```elixir
iex > Krug.NumberUtil.coalesce("1A",1)
1
```
```elixir
iex > Krug.NumberUtil.coalesce(0,1)
0
```
```elixir
iex > Krug.NumberUtil.coalesce(0,1,true)
1
```
```elixir
iex > Krug.NumberUtil.coalesce("0",1,true)
1
```
```elixir
iex > Krug.NumberUtil.coalesce(2,1)
2
```
```elixir
iex > Krug.NumberUtil.coalesce("2",1)
2
```
```elixir
iex > Krug.NumberUtil.coalesce("1.2,4",1)
12.4
```
```elixir
iex > Krug.NumberUtil.coalesce("1,2,4",1)
12.4
```
```elixir
iex > Krug.NumberUtil.coalesce("-1,2.4",1)
-12.4
```
"""
def coalesce(value,value_if_empty_or_nil,zero_as_empty \\ false) do
value = value |> StringUtil.trim()
cond do
(value == "") -> value_if_empty_or_nil
(value |> is_nan3()) -> value_if_empty_or_nil
true -> coalesce2(value,value_if_empty_or_nil,zero_as_empty)
end
end
@doc """
Verify if a value received is a valid number and is >= min
and <= max.
If the value received not is a valid number return 0.
If the ```min``` or ```max``` parameter value not is a valid number return the value received.
If value < min return min.
If value > max return max.
## Examples
```elixir
iex > Krug.NumberUtil.coalesce_interval(nil,"10","20")
0
```
```elixir
iex > Krug.NumberUtil.coalesce_interval("",10,"20")
0
```
```elixir
iex > Krug.NumberUtil.coalesce_interval("1-1",10,20)
0
```
```elixir
iex > Krug.NumberUtil.coalesce_interval("1A",10,20)
0
```
```elixir
iex > Krug.NumberUtil.coalesce_interval("101","10",nil)
101
```
```elixir
iex > Krug.NumberUtil.coalesce_interval("101","1A",20)
101
```
```elixir
iex > Krug.NumberUtil.coalesce_interval(101,10,20)
20
```
```elixir
iex > Krug.NumberUtil.coalesce_interval("5.5","10",20)
10
```
```elixir
iex > Krug.NumberUtil.coalesce_interval("15.5",10,20)
15.5
```
"""
def coalesce_interval(value,min,max) do
cond do
(is_nan(value)) -> 0
(is_nan(min) or is_nan(max)) -> numberize(value)
true -> coalesce_interval2(value,min,max)
end
end
defp coalesce_interval2(value,min,max) do
value2 = numberize(value)
min2 = numberize(min)
max2 = numberize(max)
cond do
(value2 < min2) -> min2
(value2 > max2) -> max2
true -> value2
end
end
defp numberize(value) do
cond do
(is_number(value)) -> value
true -> numberize2(value)
end
end
defp numberize2(value) do
value2 = value |> StringUtil.replace(",",".",true)
cond do
(String.contains?(value2,".")) -> to_float(value2)
true -> to_integer(value2)
end
end
defp convert_to_float(number) do
number = StringUtil.replace(number," ","",true) |> StringUtil.replace(",",".",true)
cond do
(!(String.contains?(number,"."))) -> number |> String.to_integer()
true -> handle_extra_float_dots(number) |> String.to_float()
end
end
defp handle_extra_float_dots(number) do
reversed_array = StringUtil.split(number,".") |> Enum.reverse()
double_part = hd(reversed_array)
integer_part = tl(reversed_array) |> Enum.reverse() |> IO.iodata_to_binary()
[integer_part,".",double_part] |> IO.iodata_to_binary()
end
@doc false
defp is_nan2(number) do
number = number |> StringUtil.trim()
cond do
(number == "") -> true
true -> is_nan3(number)
end
end
@doc false
defp is_nan3(number) do
cond do
(StringUtil.replace_all(number,@float_chars,"") != "") -> true
(Enum.member?([".",","],number |> StringUtil.slice(0,0))) -> true
(StringUtil.replace_all(number,@numeric_specials,"") == "") -> true
(StringUtil.contains_one_element_of_array(number,@numeric_specials_invalid)) -> true
true -> is_nan4(number)
end
end
@doc false
defp is_nan4(number) do
size = String.length(number)
number2 = cond do
(size > 1) -> number |> StringUtil.slice(1,size)
true -> number
end
StringUtil.replace_all(number2,@positive_float_chars,"") != ""
end
@doc false
defp to_positive2(number) do
cond do
(number < 0) -> (number * -1)
true -> number
end
end
@doc false
defp to_integer2(number) do
cond do
(number == "") -> 0
(number |> StringUtil.replace_all(@numerals,"") == "")
-> number |> String.to_integer()
(number |> is_nan3()) -> 0
true -> number
|> StringUtil.replace(",",".",true)
|> StringUtil.split(".")
|> hd()
|> String.to_integer()
end
end
@doc false
defp to_float_format2(number_array,decimals,comma_as_decimal_separator) do
decimal_part = number_array
|> tl()
|> get_decimal_part(decimals)
cond do
(!comma_as_decimal_separator)
-> [number_array |> hd(),".",decimal_part] |> IO.iodata_to_binary()
true
-> [number_array |> hd(),",",decimal_part] |> IO.iodata_to_binary()
end
end
@doc false
defp get_decimal_part(tail,decimals) do
cond do
(Enum.empty?(tail))
-> "" |> StringUtil.right_zeros(decimals,true)
true
-> tail |> hd() |> StringUtil.right_zeros(decimals,true)
end
end
@doc false
defp coalesce2(value,value_if_empty_or_nil,zero_as_empty) do
value = value |> StringUtil.replace(",",".",true)
cond do
(String.contains?(value,".")) -> coalesce_float(value,value_if_empty_or_nil,zero_as_empty)
true -> coalesce_integer(value,value_if_empty_or_nil,zero_as_empty)
end
end
@doc false
defp coalesce_integer(value,value_if_empty_or_nil,zero_as_empty) do
value = to_integer(value)
cond do
(zero_as_empty and value == 0)
-> value_if_empty_or_nil
true -> value
end
end
@doc false
defp coalesce_float(value,value_if_empty_or_nil,zero_as_empty) do
value = to_float(value)
cond do
(zero_as_empty and value == 0.0)
-> value_if_empty_or_nil
true -> value
end
end
end