<?php | |
function ceil_plus(float $value, ?int $precision = null): float | |
{ | |
if (null === $precision) { | |
return (float) ceil($value); | |
} | |
if ($precision < 0) { | |
throw new \RuntimeException('Invalid precision'); | |
} | |
$reg = $value + 0.5 / (10 ** $precision); | |
return round($reg, $precision, $reg > 0 ? PHP_ROUND_HALF_DOWN : PHP_ROUND_HALF_UP); | |
} | |
function floor_plus(float $value, ?int $precision = null): float | |
{ | |
if (null === $precision) { | |
return (float)floor($value); | |
} | |
if ($precision < 0) { | |
throw new \RuntimeException('Invalid precision'); | |
} | |
$reg = $value - 0.5 / (10 ** $precision); | |
return round($reg, $precision, $reg > 0 ? PHP_ROUND_HALF_UP : PHP_ROUND_HALF_DOWN); | |
} | |
// Tests for ceil_plus(). | |
assert(ceil_plus(3.14, 0) === 4.0); | |
assert(ceil_plus(3.14, 1) === 3.2); | |
assert(ceil_plus(3.14, 2) === 3.14); | |
assert(ceil_plus(3.1415, 0) === 4.0); | |
assert(ceil_plus(3.1415, 1) === 3.2); | |
assert(ceil_plus(3.1415, 2) === 3.15); | |
assert(ceil_plus(3.1415, 3) === 3.142); | |
assert(ceil_plus(3.1415, 4) === 3.1415); | |
assert(ceil_plus(0.002, 3) === 0.002); | |
assert(ceil_plus(0.0015, 3) === 0.002); | |
assert(ceil_plus(0.001, 3) === 0.001); | |
assert(ceil_plus(0, 0) === 0.0); | |
assert(ceil_plus(-0.001, 3) === -0.001); | |
assert(ceil_plus(-0.0015, 3) === -0.001); | |
assert(ceil_plus(-0.002, 3) === -0.002); | |
assert(ceil_plus(-1, 0) === -1.0); | |
// Tests for floor_plus(). | |
assert(floor_plus(3.14, 0) === 3.0); | |
assert(floor_plus(3.14, 1) === 3.1); | |
assert(floor_plus(3.14, 2) === 3.14); | |
assert(floor_plus(3.1415, 0) === 3.0); | |
assert(floor_plus(3.1415, 1) === 3.1); | |
assert(floor_plus(3.1415, 2) === 3.14); | |
assert(floor_plus(3.1415, 3) === 3.141); | |
assert(floor_plus(3.1415, 4) === 3.1415); | |
assert(floor_plus(0.002, 3) === 0.002); | |
assert(floor_plus(0.0015, 3) === 0.001); | |
assert(floor_plus(0.001, 3) === 0.001); | |
assert(floor_plus(0, 0) === 0.0); | |
assert(floor_plus(-0.001, 3) === -0.001); | |
assert(floor_plus(-0.0015, 3) === -0.002); | |
assert(floor_plus(-0.002, 3) === -0.002); | |
assert(floor_plus(-1, 0) === -1.0); |
@malsatin Hi. Thank you for your comment. I tested some patterns.
0
:
var_dump(floor_plus(0, 0)); # => float(-1). This should be float(0).
var_dump(floor_plus(0, 1)); # => float(-0.1). This should be float(0).
1
:
var_dump(floor_plus(1, 0)); # => float(1)
var_dump(floor_plus(1, 1)); # => float(1)
I confirmed the returned values for 0
are wrong. But the returned values for 1
look correct. Is my understanding correct?
@gh640
Sorry, was a bit tired. Actually it works fine for 1
. What I have would yesterday is that if works incorrectly for 0.001
var_dump(floor_plus(0.002, 3)); // => float(0.002)
var_dump(floor_plus(0.001, 3)); // => float(0)
Yesterday I have also make a working solution, with some help of StackOverflow tips. Now it also supports negative values rounding.
ceil
function ceil(float $value, ?int $precision = null): float
{
if (null === $precision) {
return (float)ceil($value);
}
if ($precision < 0) {
throw new \RuntimeException('Invalid precision');
}
$reg = $value + 0.5 / (10 ** $precision);
return round($reg, $precision, $reg > 0 ? PHP_ROUND_HALF_DOWN : PHP_ROUND_HALF_UP);
}
ceil:
function floor(float $value, ?int $precision = null): float
{
if (null === $precision) {
return (float)floor($value);
}
if ($precision < 0) {
throw new \RuntimeException('Invalid precision');
}
$reg = $value - 0.5 / (10 ** $precision);
return round($reg, $precision, $reg > 0 ? PHP_ROUND_HALF_UP : PHP_ROUND_HALF_DOWN);
}
@malsatin Thank you for your comments. Your code looks better. I'd like to update the code but I'm busy and don't have enough time now... :( I'll come back soon. Thanks!
@malsatin Sorry for my slow reaction. I tested some cases with you implementation and they look fine! I've updated the code above with some additional assertions. Thank you.
Thank you too. Hopefully this thread would help someone in the future
hi there. The function
floor_plus
would work incorrectly for0
and1
values