CodingForums.com

CodingForums.com (http://www.codingforums.com/index.php)
-   Post a PHP snippet (http://www.codingforums.com/forumdisplay.php?f=41)
-   -   Add proper ending to number (st, nd, rd, th) (http://www.codingforums.com/showthread.php?t=186972)

tspek 01-17-2010 10:44 PM

Add proper ending to number (st, nd, rd, th)
 
I'm pretty sure (though it's very possible I'm wrong) that PHP doesn't have anything built in to do this outside of dates and I searched the internet and couldn't find anything worth a darn via google.

PHP Code:

#Adds st nd rd th to appropriate numbers
function number_ending ($number)
{
    
// Get the last character of a string.
    
$str $number;
    
$string $str[strlen($str)-1];
    
$j 0;
    
    if (
$string == 1)
    {
        
$ending "st";
        ++
$j;
    }
    else if (
$string == 2)
    {
        
$ending "nd";
        ++
$j;
    }
    else if (
$string == 3)
    {
        
$ending "rd";
        ++
$j;
    }
     
    else if (
$string == 11)
           {
                
$ending "th";
               ++
$j;
           }

    else
    {
        
$ending "th";
        ++
$j;
    }
    
    if (
$j == 1)
    {
        
$number "$number"."$ending";
        return 
$number;
    }



oesxyl 01-17-2010 10:50 PM

PHP Code:

function number_ending ($number){
   
$suff = array("","st","nd","rd","th");
   
$index intval($number);
   if(
$index 4){
      
$index 4;
   }elseif(
$index 1){
      
$index 0;
   }
   return (
$number $suff[$index]);


best regards

Zoic 01-17-2010 11:01 PM

I tried oesxyl's function and it stopped working at 21 and everything ended with "th".

I found the following code on http://www.talkphp.com/tips-tricks/2...ers-dates.html and it worked like a charm. :)

PHP Code:

<?php
function show_ordinal($num) {
    
// first convert to string if needed
    
$the_num = (string) $num;
    
// now we grab the last digit of the number
    
$last_digit substr($the_num, -11);
    
// if the string is more than 2 chars long, we get
    // the second to last character to evaluate
    
if (strlen($the_num)>1) {
        
$next_to_last substr($the_num, -21);
    } else {
        
$next_to_last "";
    }
    
// now iterate through possibilities in a switch
    
switch($last_digit) {
        case 
"1":
            
// testing the second from last digit here
            
switch($next_to_last) {
                case 
"1":
                    
$the_num.="th";
                    break;
                default:
                    
$the_num.="st";
            }
            break;
        case 
"2":
            
// testing the second from last digit here
            
switch($next_to_last) {
                case 
"1":
                    
$the_num.="th";
                    break;
                default:
                    
$the_num.="nd";
            }
            break;
        
// if last digit is a 3
        
case "3":
            
// testing the second from last digit here
            
switch($next_to_last) {
                case 
"1":
                    
$the_num.="th";
                    break;
                default:
                    
$the_num.="rd";
            }
            break;
        
// for all the other numbers we use "th"
        
default:
            
$the_num.="th";
    }

    
// finally, return our string with it's new suffix
    
return $the_num;
}
?>

(I searched for php number suffix in google)

tspek 01-17-2010 11:09 PM

*Edit*

I didn't see the other response. Assuming his doesn't work, mine would be the shortest yet, does that make a difference in terms of speed?

I also just realized that 11 would come out 11st...thus requiring another another if statement...

oesxyl 01-17-2010 11:12 PM

Quote:

Originally Posted by Zoic (Post 911531)
I tried oesxyl's function and it stopped working at 21

it work for me:

PHP Code:

<?php

function number_ending($number){
  
$suff = array("","st","nd","rd","th");
  
$index intval($number);
  if(
$index 4){
    
$index 4;
  }elseif(
$index 1){
    
$index 0;
  }
  return (
$number $suff[$index]);
}

for(
$i=-1;$i<100;$i++){
  print 
number_ending($i) . "\n";
}

?>

Code:

-1
0
1st
2nd
3rd
4th
5th
6th
7th
8th
9th
10th
11th
12th
13th
14th
15th
16th
17th
18th
19th
20th
21th
22th
23th
24th
25th
26th
27th
28th
29th
30th
31th
32th
33th
34th
35th
36th
37th
38th
39th
40th
41th
42th
43th
44th
45th
46th
47th
48th
49th
50th
51th
52th
53th
54th
55th
56th
57th
58th
59th
60th
61th
62th
63th
64th
65th
66th
67th
68th
69th
70th
71th
72th
73th
74th
75th
76th
77th
78th
79th
80th
81th
82th
83th
84th
85th
86th
87th
88th
89th
90th
91th
92th
93th
94th
95th
96th
97th
98th
99th

Quote:

and everything ended with "th".
and what you expect to be instead th?

best regards

oesxyl 01-17-2010 11:15 PM

Quote:

Originally Posted by tspek (Post 911532)
*Edit*

I didn't see the other response. Assuming his doesn't work, mine would be the shortest yet, does that make a difference in terms of speed?

I also just realized that 11 would come out 11st...thus requiring another another if statement...

I mess this too, :)

tspek 01-17-2010 11:16 PM

Quote:

Originally Posted by oesxyl (Post 911533)
it work for me:

[php]
and what you expect to be instead th?

best regards


33 would be 33rd not 33th.

oesxyl 01-17-2010 11:17 PM

just fix the problem:
PHP Code:

function number_ending ($number){
   
$suff = array("","st","nd","rd","th");
   
$index intval($number) % 10;
   if(
$index 4){
      
$index 4;
   }elseif(
$index 1){
      
$index 0;
   }
   return (
$number $suff[$index]);


best regards

oesxyl 01-17-2010 11:24 PM

Quote:

Originally Posted by tspek (Post 911538)
33 would be 33rd not 33th.

same like what you post in #1, I also mess it and everything after 3 ends in th.
I fix this in #8. I don't know which is faster, mine is obvious shorter.

best regards

oesxyl 01-18-2010 12:22 AM

seems that previous was incorrect, see 11st, 12nd, 13rd vs. 11th, 12th, 13th:
Fixed:
PHP Code:

<?php
/*
 * seeAlso:
 *    http://en.wikipedia.org/wiki/Names_of_numbers_in_English#Ordinal_numbers
 *
 * 0, 1st, 2nd, 3rd, 4th, ...
 * 10th, 11th, 12th, 23th, ...
 * 20th, 21st, 22nd, 33rd, 34th
 */
function number_ending($number){
  
$n intval($number);
  
$suff = array("","st","nd","rd","th");
  
$index $n 10// index ok for 0-9, i1-i9 (i > 2)
  
if($index || ($index == && $n 0) || ($n 10 && $n 20)){
    
$index 4;
  }elseif(
$index 1){
    
$index 0;
  }
  return (
$number $suff[$index]);
}

// test:
for($i=-1;$i<100;$i++){
  print 
number_ending($i) . "\n";
}

?>

best regards

kbluhm 01-18-2010 12:33 AM

PHP Code:

function ordinalize$number )
{
    if ( 
is_numeric$number ) && <> $number )
    {
        if ( 
in_array$number 100range1113 ) ) )
        {
            return 
$number 'th';
        }
        switch ( 
$number 10 )
        {
            case 
1:  return $number 'st';
            case 
2:  return $number 'nd';
            case 
3:  return $number 'rd';
            default: return 
$number 'th';
        }
    }
    return 
$number;



tspek 01-22-2010 03:32 PM

I'm very new to PHP and programming in general. It's becoming increasingly clearer that there is more than one way to do just about anything and ultimately it comes down to using the most efficient method available.

The question then is how we know which way is the most efficient.

Here we have 3 functions that all do the same thing different ways, which one works the best though?

Fou-Lu 01-22-2010 04:16 PM

Thats trickier to answer. When it comes to algorithms, most of them can be calculated by an order of magnitude. Since these all have an O(1) magnitude, they are all technically as efficient from a magnitude view. Magnitude really only cares about the 'big' picture as a whole.

So, look at other factors. Datatypes are my primary concern. If you treat you're number as a string, you will waste time and resource, but looking at the last digit itself is a matter of a char lookup. So, should the number be interpreted as a string, any string > 4 characters in length has exceeded the memory size required for any number storable as an integer (and this will increase in PHP6 which is going to native unicode).

kbluhm and oesxyl have both ensured that they are working with numbers. Oesyxl's approach is slightly more efficient, but will not tell you if its actually a number (and therefore becomes untrappable). It doesn't care if you give it a string, if you do it will cast it to a number. I believe that the is_* functions are slightly less efficient than direct casting. The benifit is you can toss and trap errors associated with this approach.

Though the codes are negligable, efficiency wise I expect that oesxyl's will be slightly faster in execution time; however, like I mentioned there is little that can be done to trigger / throw and trap any errors from it since it technically cannot have any errors with the explicit casting. Oesxyl's appears to also waste a little more memory than kbluhm's method since it declares two local variables (since the third is a write-on-copy context).
Weight on weight, I'll bet if I tested these to benchmark on precision to 1000, they would come up identical. At 100000, I'd suspect to see a 5 - 8 variance, which is incredibly tiny.

Also, one more factor is readability. Efficiency is IMO tossable for readability in languages like PHP. We're not doing embedded microprocessing, so memory and cpu are not really an issue nowadays. You can certainly take a more readable approach so you can understand later what you've done without needing to walk through it step by step (from the above, kbluhm's is more readable than oesxyl's).

oesxyl 01-22-2010 04:18 PM

Quote:

Originally Posted by tspek (Post 913786)
I'm very new to PHP and programming in general. It's becoming increasingly clearer that there is more than one way to do just about anything and ultimately it comes down to using the most efficient method available.

The question then is how we know which way is the most efficient.

Here we have 3 functions that all do the same thing different ways, which one works the best though?

depend of what do you mean by "works the best". :)

best regards

Cjwinnit 10-21-2011 05:44 PM

My thoughts:
PHP Code:

function ordinal $ordnum ) {
  
$ordinalsuffixes = array("th","st","nd","rd");
  for(
$i=1;$i<=3;$i++) { if(($ordnum 10 == $i) && ($ordnum 100 != 10+$i )) return $ordinalsuffixes[$i]; }
return 
$ordinalsuffixes[0] ;    } 

If you wanted an error-check you could insert this as the first line in the func.:
PHP Code:

  if(!((gettype($ordnum) == "integer") && ($ordnum 0))) return false

I think I win for the shortest code. Cookie? ;)


All times are GMT +1. The time now is 11:15 PM.

Powered by vBulletin®
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.