Add precision to Float.ceil/1 & Float.floor/1
This commit is contained in:
committed by
Hashrocket Workstation
parent
bba4f1bd1b
commit
583a4ec5f6
+35
-18
@@ -98,54 +98,67 @@ defmodule Float do
|
||||
|
||||
@doc """
|
||||
Rounds a float to the largest integer less than or equal to `num`.
|
||||
Floor also accepts a precision to round a floating point value down
|
||||
to an arbitrary number of fractional digits (between 0 and 15).
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Float.floor(34)
|
||||
34
|
||||
|
||||
iex> Float.floor(34.25)
|
||||
34
|
||||
34.0
|
||||
|
||||
iex> Float.floor(-56.5)
|
||||
-57
|
||||
-57.0
|
||||
|
||||
iex> Float.floor(34.253, 2)
|
||||
34.25
|
||||
|
||||
"""
|
||||
@spec floor(float | integer) :: integer
|
||||
def floor(num) when is_integer(num), do: num
|
||||
@spec floor(float) :: float
|
||||
def floor(num) when is_float(num) do
|
||||
truncated = :erlang.trunc(num)
|
||||
case :erlang.abs(num - truncated) do
|
||||
x when x > 0 and num < 0 -> truncated - 1
|
||||
_ -> truncated
|
||||
x when x > 0 and num < 0 -> truncated - 1.0
|
||||
_ -> truncated + 0.0
|
||||
end
|
||||
end
|
||||
|
||||
@spec floor(float, integer) :: float
|
||||
def floor(num, precision) when is_float(num) do
|
||||
calculate_precision(num, -0.5, precision) |> round(precision)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Rounds a float to the largest integer greater than or equal to `num`.
|
||||
Ceil also accepts a precision to round a floating point value down to
|
||||
an arbitrary number of fractional digits (between 0 and 15).
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Float.ceil(34)
|
||||
34
|
||||
|
||||
iex> Float.ceil(34.25)
|
||||
35
|
||||
35.0
|
||||
|
||||
iex> Float.ceil(-56.5)
|
||||
-56
|
||||
-56.0
|
||||
|
||||
iex> Float.ceil(34.253, 2)
|
||||
34.26
|
||||
|
||||
"""
|
||||
@spec ceil(float | integer) :: integer
|
||||
def ceil(num) when is_integer(num), do: num
|
||||
|
||||
@spec ceil(float) :: float
|
||||
def ceil(num) when is_float(num) do
|
||||
truncated = :erlang.trunc(num)
|
||||
case :erlang.abs(num - truncated) do
|
||||
x when x > 0 and num > 0 -> truncated + 1
|
||||
_ -> truncated
|
||||
x when x > 0 and num > 0 -> truncated + 1.0
|
||||
_ -> truncated + 0.0
|
||||
end
|
||||
end
|
||||
|
||||
@spec ceil(float, integer) :: float
|
||||
def ceil(num, precision) when is_float(num) do
|
||||
calculate_precision(num, 0.5, precision) |> round(precision)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Rounds a floating point value to an arbitrary number of fractional digits
|
||||
(between 0 and 15).
|
||||
@@ -247,6 +260,10 @@ defmodule Float do
|
||||
:erlang.float_to_binary(float, expand_compact(options))
|
||||
end
|
||||
|
||||
defp calculate_precision(num, variance, precision) do
|
||||
num + (variance / :math.pow(10, precision))
|
||||
end
|
||||
|
||||
defp expand_compact([{:compact, false}|t]), do: expand_compact(t)
|
||||
defp expand_compact([{:compact, true}|t]), do: [:compact|expand_compact(t)]
|
||||
defp expand_compact([h|t]), do: [h|expand_compact(t)]
|
||||
|
||||
@@ -28,35 +28,41 @@ defmodule FloatTest do
|
||||
end
|
||||
|
||||
test :floor do
|
||||
assert Float.floor(12) === 12
|
||||
assert Float.floor(-12) === -12
|
||||
assert Float.floor(12.524235) === 12
|
||||
assert Float.floor(-12.5) === -13
|
||||
assert Float.floor(-12.524235) === -13
|
||||
assert Float.floor(7.5e3) === 7500
|
||||
assert Float.floor(7.5432e3) === 7543
|
||||
assert Float.floor(7.5e-3) === 0
|
||||
assert Float.floor(-12.32453e4) === -123246
|
||||
assert Float.floor(-12.32453e-10) === -1
|
||||
assert Float.floor(0.32453e-10) === 0
|
||||
assert Float.floor(-0.32453e-10) === -1
|
||||
assert Float.floor(1.32453e-10) === 0
|
||||
assert Float.floor(12.524235) === 12.0
|
||||
assert Float.floor(-12.5) === -13.0
|
||||
assert Float.floor(-12.524235) === -13.0
|
||||
assert Float.floor(7.5e3) === 7500.0
|
||||
assert Float.floor(7.5432e3) === 7543.0
|
||||
assert Float.floor(7.5e-3) === 0.0
|
||||
assert Float.floor(-12.32453e4) === -123246.0
|
||||
assert Float.floor(-12.32453e-10) === -1.0
|
||||
assert Float.floor(0.32453e-10) === 0.0
|
||||
assert Float.floor(-0.32453e-10) === -1.0
|
||||
assert Float.floor(1.32453e-10) === 0.0
|
||||
end
|
||||
|
||||
test :floor_with_precision do
|
||||
assert Float.floor(12.524235, 2) === 12.52
|
||||
assert Float.floor(-12.524235, 3) === -12.525
|
||||
end
|
||||
|
||||
test :ceil do
|
||||
assert Float.ceil(12) === 12
|
||||
assert Float.ceil(-12) === -12
|
||||
assert Float.ceil(12.524235) === 13
|
||||
assert Float.ceil(-12.5) === -12
|
||||
assert Float.ceil(-12.524235) === -12
|
||||
assert Float.ceil(7.5e3) === 7500
|
||||
assert Float.ceil(7.5432e3) === 7544
|
||||
assert Float.ceil(7.5e-3) === 1
|
||||
assert Float.ceil(-12.32453e4) === -123245
|
||||
assert Float.ceil(-12.32453e-10) === 0
|
||||
assert Float.ceil(0.32453e-10) === 1
|
||||
assert Float.ceil(-0.32453e-10) === 0
|
||||
assert Float.ceil(1.32453e-10) === 1
|
||||
assert Float.ceil(12.524235) === 13.0
|
||||
assert Float.ceil(-12.5) === -12.0
|
||||
assert Float.ceil(-12.524235) === -12.0
|
||||
assert Float.ceil(7.5e3) === 7500.0
|
||||
assert Float.ceil(7.5432e3) === 7544.0
|
||||
assert Float.ceil(7.5e-3) === 1.0
|
||||
assert Float.ceil(-12.32453e4) === -123245.0
|
||||
assert Float.ceil(-12.32453e-10) === 0.0
|
||||
assert Float.ceil(0.32453e-10) === 1.0
|
||||
assert Float.ceil(-0.32453e-10) === 0.0
|
||||
assert Float.ceil(1.32453e-10) === 1.0
|
||||
end
|
||||
|
||||
test :ceil_with_precision do
|
||||
assert Float.ceil(12.524235, 2) === 12.53
|
||||
assert Float.ceil(-12.524235, 3) === -12.524
|
||||
end
|
||||
|
||||
test :round do
|
||||
|
||||
Reference in New Issue
Block a user