Add precision to Float.ceil/1 & Float.floor/1

This commit is contained in:
Johnny Winn
2014-07-11 12:34:24 -04:00
committed by Hashrocket Workstation
parent bba4f1bd1b
commit 583a4ec5f6
2 changed files with 67 additions and 44 deletions
+35 -18
View File
@@ -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)]
+32 -26
View File
@@ -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