
|
View Full Version : [PHP] Round a decimal number up?
jonathanbull 10-08-2009, 10:11 PM Hi,
I've wasted a huge amount of time on solving something which should be relatively easy. Am I just being stupid?
I'd like to always round a decimal number up to the nearest hundreth. For example...
1.5388 = 1.54
1.5312 = 1.54
1.53 = 1.53
Ceil seems to only be for integers, and round and number_format can't always round up. I know that adding 0.005 on first is an option, you can even stick an if statement in to catch if it already just has 2 DF. This seems like a dirty way of doing things though, is there a cleaner way of doing this?
Thanks in advance! :)
foobic 10-08-2009, 10:20 PM ceil should be the answer, specifically ceil(100x)/100. (Edit. nvm - I see where you were coming from.)
jonathanbull 10-08-2009, 10:35 PM ceil should be the answer, specifically ceil(100x)/100. (Edit. nvm - I see where you were coming from.)
Yup tried that - always rounds up to an integer. Thanks anyway, I told you it was harder than it looks :stickout:
foobic 10-08-2009, 10:47 PM Yes, ceil rounds up to an integer. That's why what you want ceil(100 x your number).
<?php
print centceil(1.5388) . "\n"; // 1.54
print centceil(1.5312) . "\n"; // 1.54
print centceil(1.53) . "\n"; // 1.53
function centceil($float) {
return ceil($float*100)/100;
}
?>
tim2718281 10-09-2009, 03:44 AM Hi,
I've wasted a huge amount of time on solving something which should be relatively easy. Am I just being stupid?
I'd like to always round a decimal number up to the nearest hundreth. For example...
1.5388 = 1.54
1.5312 = 1.54
1.53 = 1.53
Ceil seems to only be for integers, and round and number_format can't always round up. I know that adding 0.005 on first is an option, you can even stick an if statement in to catch if it already just has 2 DF. This seems like a dirty way of doing things though, is there a cleaner way of doing this?
Thanks in advance! :)
For positive numbers:
Multiply by 100
Add .99
Take the integer part.
Divide by 100.
y = floor(100*x + 0.99) / 100
Here's a test program:
<?php
function roundup2($x)
{
return floor(100*$x + 0.99) / 100;
}
echo 1.5388 , " " , roundup2(1.5388) , "\n";
echo 1.5312 , " " , roundup2(1.5312) , "\n";
echo 1.53 , " " , roundup2(1.53) , "\n" ;
?>
To handle negative numbers, you have to decide which way is "up".
jonathanbull 10-11-2009, 06:47 PM Thank you for all your replies. Works perfectly and I've learnt an awful lot!
tim2718281 10-11-2009, 11:02 PM Thank you for all your replies. Works perfectly and I've learnt an awful lot!
In case anyone did not realise, my suggestion gives incorrect answers for numbers such as 1.53001
There's a question of what the precision requirement is; I mistakenly assumed that four decimal digits of precision were required.
Really. the programmer should ask what precision is required, and not assume something.
mwatkins 10-12-2009, 11:59 AM Another approach - use whatever is built into PHP's type conversion mechanism:
echo (sprintf("%01.2f", 1.53001) + 0);
1.53
echo gettype(sprintf("%01.2f", 1.53001) + 0);
double
ps: Obligatory Python example:
>>> round(1.53001, 2)
1.53
>>> type(round(1.53001, 2))
float(x) -> floating point number
<class 'float'>
tim2718281 10-13-2009, 08:46 AM But input of 1.53001 is suppose to deliver 1.54, not 1.53
I guess I've confused the issue with my earlier comment.
Anyway, here is a test program:
<?php
print "1.53 Should deliver 1.53" . " : " . roundup2(1.53) . "\n"; // 1.53
print "1.531 Should deliver 1.54" . " : " . roundup2(1.531) . "\n";
print "1.5301 Should deliver 1.54" . " : " . roundup2(1.5301) . "\n";
print "1.53001 Should deliver 1.54" . " : " . roundup2(1.53001) . "\n";
print "1.53000000000000000001 Should deliver 1.54" . " : " . roundup2(1.530000000000000001) . "\n";
function roundup2($x) {
return ceil($x*100)/100;
}
?>
If you execute it, you'll likely find that the last test case gives the wrong answer.
mwatkins 10-13-2009, 11:02 AM But input of 1.53001 is suppose to deliver 1.54, not 1.53
Not in any math text I've ever read. You'd have to write a new, somewhat arbitrary, rounding rule to get that answer. Your inputs calculated using round(n, 2):
def roundemup():
print "1.53 Tim says should deliver 1.53 : but does deliver %s" % round(1.53, 2)
print "1.531 Tim says should deliver 1.54 : but does deliver %s" % round(1.531, 2)
print "1.5301 Tim says should deliver 1.54 : but does deliver %s" % round(1.5301, 2)
print "1.53001 Tim says should deliver 1.54 : but does deliver %s" % round(1.53001, 2)
print "1.53000000000000000001 Tim says should deliver 1.54 : but does deliver %s" % round(1.530000000000000001, 2)
>>> roundemup()
1.53 Tim says should deliver 1.53 : but does deliver 1.53
1.531 Tim says should deliver 1.54 : but does deliver 1.53
1.5301 Tim says should deliver 1.54 : but does deliver 1.53
1.53001 Tim says should deliver 1.54 : but does deliver 1.53
1.53000000000000000001 Tim says should deliver 1.54 : but does deliver 1.53
tim2718281 10-13-2009, 11:46 AM Not in any math text I've ever read. You'd have to write a new, somewhat arbitrary, rounding rule to get that answer. ...
Ah, you missed the stated requirement in post 1 of this thread:
"I'd like to always round a decimal number up to the nearest hundreth. For example...
1.5388 = 1.54
1.5312 = 1.54
1.53 = 1.53 "
I guess I confused the issue. Sorry about that.
mwatkins 10-13-2009, 12:47 PM Mea culpa, sorry for the distraction, thread.
You are absolutely right. I must have read that requirement and must have rejected it subconsciously as being non-sensible, to me, when the OP may have a perfectly legitimate reason for wanting same. In my own defence there are unfortunately a lot of folks who post here specifications they don't really mean, and while that isn't the case here, it seems more often than not that the community has to do some inferring and mind-reading to get to the real need. Sorry for taking things off track further folks.
I guess the least I could do is give the Python equivalent, which looks the same as Tim's function, and a test. Oh, and lets through a negative number in there... I suspect the PHP ceil approach chokes on that in the following manner:
>>> math.ceil(-1.530001*100)/100
-1.53
>>> math.ceil(1.530001*100)/100
1.54
A negative number-proof Python solution:
from math import ceil, pow
def founder(n, precision):
"""(n:int|float, precision:int) -> float
A non standard round() function.
Always round "up" to the next <precision>th, or "down" if n is negative
i.e. founder(1.530001, 2) == 1.54; founder(-1.530001, 2) == -1.54
"""
p = pow(10, precision)
return ceil(n*p)/p if n >= 0 else ceil(abs(n)*p)/(p * -1)
A test:
>>> for x in [1.54, 1.5300000001, 1.535, 1.539, 1.53123456789,
... -1.54, -1.5300000001, -1.535, -1.539, -1.53123456789]:
... print founder(x, 2)
...
1.54
1.54
1.54
1.54
1.54
-1.54
-1.54
-1.54
-1.54
-1.54
foobic 10-13-2009, 05:16 PM If you execute it, you'll likely find that the last test case gives the wrong answer.When you try to exceed the precision of floating point maths functions you're always liable to get unexpected results. Higher precision (even arbitrary-precision) functions and libraries are available for most languages if this is an issue.
Gregborbonus 10-13-2009, 07:53 PM I do apologize for the following, as I do not have the time to actually code this out for you, but I'd suggest doing the following:
split the string at the 100th place:
1.34000000001 becomes: 1.34 in string1 and 000000001 in string2.
if string2 > 0, add .01 to string1.
otherwise, do nothing.
Not the nicest of code ideas, but you could throw it in a function and call it whatever you want, then simply:
functionname(string)
Hope this helps.
|