php number formating...
Hi guys,
Does anyone know how to take a number (between 1 and 99) and ensure that if it's less than ten it's always formatted with a leading zero (i.e. 02)?
I'm assuming it can be done with the number_format function, but I can't get my head around the syntax...
Anyone?
Andy
andy206uk posted this at 21:39 — 16th December 2006.
He has: 1,758 posts
Joined: Jul 2002
ok... I worked out a way to do it (without number_format - see below), but I have a feeling it's really inefficient - especially because I have to repeat this several times when I loop through an array.
<?php
if(strlen($value) == 1) {
$value = '0'.$value;
}
?>
Do you think this will be ok, or would the number_format way be better? I need the function it's in to be as efficient as possible as it's the backbone of the whole project and could potentially see a lot of traffic.
Any help would be really appreciated
Andy
JeevesBond posted this at 22:24 — 16th December 2006.
He has: 3,956 posts
Joined: Jun 2002
Well either way your going to have to convert a number to a string, a better method might be to use sprintf. For example:
<?php
$value = sprintf('%02s',$value);
?>
number_format is for decimal points and thousand seperators (as far as I can tell), probably why you can't work out how to use it for what you want to do. More of those esoteric PHP function names, you'd think that number_format should do what you need.
sprintf comes from c, in case anyone's interested.
a Padded Cell our articles site!
andy206uk posted this at 22:55 — 16th December 2006.
He has: 1,758 posts
Joined: Jul 2002
Thanks Jeeves, if nothing else it's shrunk my code down from 5 lines to one!
Abhishek Reddy posted this at 02:44 — 17th December 2006.
He has: 3,348 posts
Joined: Jul 2001
I would have guessed that [incode]sprintf[/incode] was more efficient. It's a call to what should be a compiled (native?) function, rather than an interpreted block. And the PHP implementation also has the opportunity to optimise it in other ways that would be tricky in user code.
However, sprintf appears to be slower. I ran a quick set of tests timing both methods on a large (1.5MB) array, from the PHP command line. I used PHP 5.1.6/Zend on GNU/Linux.
<?php
$a = array(1, 2, 3 ... 200, 1, 2, 3 ... 200 ...);
foreach ($a as &$v) {
if (strlen($v) == 1) $v='0'.$v; //conditional dot
// or:
$v = sprintf('%02s',$v); //sprintf
//or:
if (strlen($v) == 1) $v = sprintf('%02s',$v); //conditional sprintf
}
?>
Executed with:
$ time php /path/to/sprintf-profile.php
Results for 20 runs each:
[incode]sprintf[/incode]: mean of 235 ms and s.d. of 3.54 ms.
conditional [incode]sprintf[/incode]: mean of 199 ms and s.d. of 3.82 ms. [Edit: fixed typo.]
conditional dot: mean of 197 ms and s.d. of 4.86 ms.
I think the dot syntax is more heavily optimised, and calling [incode]sprintf[/incode] is not cheap anyway.
Of course, this isn't a particularly good test, as it may depend on what platform, PHP version and extensions you run. And my input array could probably be better. And this doesn't say anything about growth.
You might like to try it on your host machine too, with the kind of data you expect, before making a decision.
In any case, the difference isn't huge. I'd go with [incode]sprintf[/incode] because I find it more readable. It's probably not worth saving 40 ms here.
Abhishek Reddy posted this at 04:16 — 17th December 2006.
He has: 3,348 posts
Joined: Jul 2001
Okay, seems a lot of the overhead in the conditional ones is from the [incode]strlen[/incode] call. Numeric comparison is faster:
<?php
if($v < 10 && $v > 0) $v = sprintf('%02s',$v);
?>
has a mean of 169 ms and s.d. 3.81 ms.
<?php
if($v < 10 && $v > 0) $v = '0'.$v;
?>
has a mean of 163 ms and s.d. of 3.81 ms.
Abhishek Reddy posted this at 04:34 — 17th December 2006.
He has: 3,348 posts
Joined: Jul 2001
Using double quotes instead of single quotes cuts it further:
<?php
if($v < 10 && $v > 0) $v = sprintf(\"%02s\",$v);
?>
has a mean of 158 ms and s.d. 3.18 ms.
<?php
if($v < 10 && $v > 0) $v = \"0\".$v;
?>
has a mean of 157 ms and s.d. 3.36 ms.
Sorry if this is more than you wanted to know! I'm curious to see just how much this can be optimised. I'd say this is nearing the limit, though.
JeevesBond posted this at 08:03 — 17th December 2006.
He has: 3,956 posts
Joined: Jun 2002
Well this is all a bit weird. I thought anything inside single quotes was a literal, so assumed processing time would be less. Suppose most PHP applications I've seen have used double-quotes so must be wrong!
So would I for the same reasons!
It's interesting that you managed to optimise that code Abhishek. Wonder how many processor cycles are wasted in the world every day? Hmmm, thinking like that will probably make me go insane.
Only slight flaw with the numeric comparison is that you're assuming that variable is a number. What would happen if it were a marmot? Or a duck? Then you'd be in trouble.
*** EDIT ***
What figure do you use for the timing? 'real', 'user' or 'sys'?
Was messing around with this test too. Am getting pretty similar results to you: I seem to have a smaller array though. What did you do to get such a gigantic set of numbers?
a Padded Cell our articles site!
Abhishek Reddy posted this at 08:59 — 17th December 2006.
He has: 3,348 posts
Joined: Jul 2001
See, now that's what I thought too, since variable and other fancy things are processed in double quotes, right? I have no idea why it turns out faster for me. I thought maybe my system load changed or something, but it seems not to be the case.
Comparatively, not many are wasted like this. These optimisations are implementation-specific, systemic tweaks that adjust the algorithm's growth by small constants. Many more cycles are wasted when people choose an inefficient algorithm in the first place, optimised or not.
Uhmm... I'd duckument it carefully and blame the quack who sent the bad inputs!
Seriously. One only optimises like this once all the interfaces/protocols are stable. I assumed Andy knew for sure that he had an array of integers.
In case of an error, an exception ought to be thrown and caught, anyway. Like an UnexpectedMarmotException. Or something.
Real.
I generated the sequence using two loops in Emacs. Wasn't aiming for 1.5MB, that was arbitrary. Could have used range() in PHP too.
andy206uk posted this at 13:40 — 17th December 2006.
He has: 1,758 posts
Joined: Jul 2002
Whoaaaaaaa. Thanks for all that. It's gonna take me a while to get my head round it, but every nanosecond I can save is good as far as I'm concerned
Thanks again guys!
Andy
Want to join the discussion? Create an account or log in if you already have one. Joining is fast, free and painless! We’ll even whisk you back here when you’ve finished.