While looking at PHP.net this afternoon, I saw a comment in round()
for two functions for rounding UP
and DOWN
(as opposed to just HALF_UP
and DOWN
). I liked the suggestion, but wanted a solution that was one function instead of 3, so I came up with the following:
define('PHP_ROUND_UP', 11);
define('PHP_ROUND_DOWN', 12);
function fround($number, $precision = 0, $mode = PHP_ROUND_HALF_UP) {
if(is_string($number)) {
$number = preg_replace('/,/','',$number);
}
if (is_numeric($number) && !empty($number)) {
switch($mode) {
case PHP_ROUND_UP:
case PHP_ROUND_DOWN:
$invert = (bool) ($number < 0);
if($invert) {
$number *= -1;
}
if (!empty($precision)) {
$precision = pow(10, (int) $precision);
$number *= $precision;
}
if ($mode == PHP_ROUND_UP) {
$number = ceil($number);
} else {
$number = floor($number);
}
if (!empty($precision) && !empty($number)) {
$number /= $precision;
}
if($invert) {
$number *= -1;
}
break;
default:
$number = round($number, $precision, $mode);
break;
}
}
return (float) $number;
}
My questions are about overhead/performance, and really anything else you may have to say. For options other than PHP_ROUND_UP
or PHP_ROUND_DOWN
it adds minimal overhead, save for stripping commas if the input number is a string (I realize this is additional to what PHP's round()
does), so I guess I am asking about the internal logic for PHP_ROUND_UP
and PHP_ROUND_DOWN
.
The comment that sparked this for me is here.
-
2\$\begingroup\$ Mike, if you have taken advice from the answer given to change your code, then you should post a new question with your new code. We have a policy about changing the code or the question after reviews have been given. What you may and may not do after receiving answers \$\endgroup\$Malachi– Malachi2015年12月30日 19:22:51 +00:00Commented Dec 30, 2015 at 19:22
-
1\$\begingroup\$ 10-4, I just did a quick browse on Meta to double-check, as posting a new CR for every revision seems like it would add a considerable amount of data to SO, but, indeed, it seems that all Meta questions on the topic are all about un-reviewed code, and the handful about reviewed code are just that: "Post again." My bad. \$\endgroup\$Mike– Mike2015年12月30日 19:27:33 +00:00Commented Dec 30, 2015 at 19:27
-
1\$\begingroup\$ Side-Note: It would be nice if there was a "Post Revision" button, that created a link to the new revision, would help tying them all together, direct the crowd/conversation, etc. It would also make the requirement clearer. Maybe I will mention this on Meta. \$\endgroup\$Mike– Mike2015年12月30日 19:29:37 +00:00Commented Dec 30, 2015 at 19:29
1 Answer 1
General
Instead of having your function convert string values to numbers, throw an error if, for example !is_float($number)
. round()
only accepts a float value, so I think you should follow their convention.
Also, this will allow you to remove is_numeric()
(or, above, you could check for is_numeric()
only).
This if-condition doesn't have an else, so when poor input is entered, the user could potentially not get any response at all -- terrible for debugging!
Performance
empty($number)
is checked two times, you can reduce that to none since is_float()
will automatically return false if there is nothing (or throw an error is there's no argument).
-
\$\begingroup\$ Yes, the
preg_replace
deviates fromround()
's convention, and probably should not be included, but I put it in my function because it deals with some numbers from a DB, I may modify to filter outside the function first. I thinkis_numeric()
is appropriate, asround()
accepts any numeric value. As for getting "nothing," the function will return an empty(float)
, which follows convention0 === round('hello');
As for$invert
, this is nessesary to mimicround()
behaviour with negative numbers-124 === round(-123.5) && 124 === round(123.5)
. I will clean up. \$\endgroup\$Mike– Mike2015年12月30日 19:01:52 +00:00Commented Dec 30, 2015 at 19:01 -
\$\begingroup\$ @Mike On second glance,
is_numeric()
is comparable to what's inround()
, so that's fine. And$invert
seems appropriate, I hadn't used round() in a while and had to go test it out! \$\endgroup\$Alex L– Alex L2015年12月30日 19:08:40 +00:00Commented Dec 30, 2015 at 19:08 -
1\$\begingroup\$ Updated, the use of
xor
is much more performant, and I LOVE getting a chance to use it when I can. \$\endgroup\$Mike– Mike2015年12月30日 19:13:29 +00:00Commented Dec 30, 2015 at 19:13 -
\$\begingroup\$ Haha very clever, if I think of anything else I'll edit my answer! \$\endgroup\$Alex L– Alex L2015年12月30日 19:15:13 +00:00Commented Dec 30, 2015 at 19:15