php number formating...

He has: 1,758 posts

Joined: Jul 2002

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... Confused

Anyone?

Andy

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 Laughing out loud

Andy

JeevesBond's picture

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. Smiling

sprintf comes from c, in case anyone's interested.

a Padded Cell our articles site!

He has: 1,758 posts

Joined: Jul 2002

Thanks Jeeves, if nothing else it's shrunk my code down from 5 lines to one! Laughing out loud

Abhishek Reddy's picture

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.

Smiling

Abhishek Reddy's picture

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.

Smiling

Abhishek Reddy's picture

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. Smiling

JeevesBond's picture

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!

Abhishek wrote: I would have guessed that sprintf was more efficient.

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. Smiling

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. Smiling

*** 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? Smiling

a Padded Cell our articles site!

Abhishek Reddy's picture

He has: 3,348 posts

Joined: Jul 2001

JeevesBond;212256 wrote: Well this is all a bit weird. I thought anything inside single quotes was a literal, so assumed processing time would be less.

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. Confused

JeevesBond;212256 wrote: It's interesting that you managed to optimise that code Abhishek. Wonder how many processor cycles are wasted in the world every day?

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. Sad

JeevesBond;212256 wrote: 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. Smiling

Uhmm... I'd duckument it carefully and blame the quack who sent the bad inputs! Sticking out tongue

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. Sticking out tongue

JeevesBond;212256 wrote: What figure do you use for the timing? 'real', 'user' or 'sys'?

Real.

JeevesBond;212256 wrote: 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? Smiling

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.

Smiling

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 Laughing out loud

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.