代码之家  ›  专栏  ›  技术社区  ›  ArK Sheeba Nancy

在PHP中显示带序数后缀的数字

  •  125
  • ArK Sheeba Nancy  · 技术社区  · 15 年前

    我想把数字显示如下

    • 1等于第一,
    • 2等于第二,
    • 150为第一百五十。

    如何在代码中为每个数字找到正确的序数后缀(st、nd、rd或th)?

    16 回复  |  直到 6 年前
        1
  •  251
  •   neshkeev    10 年前

    from wikipedia :

    $ends = array('th','st','nd','rd','th','th','th','th','th','th');
    if (($number %100) >= 11 && ($number%100) <= 13)
       $abbreviation = $number. 'th';
    else
       $abbreviation = $number. $ends[$number % 10];
    

    在哪里? $number 是您要写的号码。适用于任何自然数。

    作为一个函数:

    function ordinal($number) {
        $ends = array('th','st','nd','rd','th','th','th','th','th','th');
        if ((($number % 100) >= 11) && (($number%100) <= 13))
            return $number. 'th';
        else
            return $number. $ends[$number % 10];
    }
    //Example Usage
    echo ordinal(100);
    
        2
  •  115
  •   Community CDub    13 年前

    PHP has built-in functionality for this . 它甚至处理国际化!

    $locale = 'en_US';
    $nf = new NumberFormatter($locale, NumberFormatter::ORDINAL);
    echo $nf->format($number);
    

    请注意,此功能仅在php 5.3.0及更高版本中可用。

        3
  •  16
  •   Andrew Kozak    8 年前

    这可以通过在PHP的内置日期/时间函数中利用类似的功能在一行中完成。我谦虚地提交:

    解决方案:

    function ordinalSuffix( $n )
    {
      return date('S',mktime(1,1,1,1,( (($n>=10)+($n>=20)+($n==0))*10 + $n%10) ));
    }
    

    详细说明:

    内置的 date() 函数的后缀逻辑用于处理每月第n天的计算。当 S 格式字符串中给出:

    date( 'S' , ? );
    

    自从 数据() 需要时间戳(用于 ? 上面),我们将传递整数 $n 作为 day 参数到 mktime() 并使用虚拟值 1 对于 hour , minute , second month :

    date( 'S' , mktime( 1 , 1 , 1 , 1 , $n ) );
    

    这实际上在一个月中的某一天(即 $n > 31 )但是我们可以在cap中添加一些简单的内联逻辑 $N 29岁:

    date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20))*10 + $n%10) ));
    

    唯一的正值 ( 2017年5月 )这个失败是 $n == 0 但在这种特殊情况下,只需增加10个就可以很容易地解决这个问题:

    date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20)+($n==0))*10 + $n%10) ));
    

    更新,2017年5月

    如@donatj所观察到的,上述故障超过100(例如“111st”),因为 >=20 支票总是返回真的。为了每一个世纪都重置这些,我们在比较中添加了一个过滤器:

    date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n%100>=20)+($n==0))*10 + $n%10) ));
    

    把它包装在一个方便的功能中就行了!

        4
  •  14
  •   Paul    8 年前

    这是一条单线:

    $a = <yournumber>;
    echo $a.substr(date('jS', mktime(0,0,0,1,($a%10==0?9:($a%100>20?$a%10:$a%100)),2000)),-2);
    

    可能是最短的解决方案。当然可以用函数包装:

    function ordinal($a) {
      // return English ordinal number
      return $a.substr(date('jS', mktime(0,0,0,1,($a%10==0?9:($a%100>20?$a%10:$a%100)),2000)),-2);
    }
    

    当做, 保罗

    edit1:修正11到13的代码。

    编辑2:修正111,211,…

    伊迪丝3:现在它也能正确地适用于10的倍数。

        5
  •  13
  •   John Boker    15 年前

    http://www.phpro.org/examples/Ordinal-Suffix.html

    <?php
    
    /**
     *
     * @return number with ordinal suffix
     *
     * @param int $number
     *
     * @param int $ss Turn super script on/off
     *
     * @return string
     *
     */
    function ordinalSuffix($number, $ss=0)
    {
    
        /*** check for 11, 12, 13 ***/
        if ($number % 100 > 10 && $number %100 < 14)
        {
            $os = 'th';
        }
        /*** check if number is zero ***/
        elseif($number == 0)
        {
            $os = '';
        }
        else
        {
            /*** get the last digit ***/
            $last = substr($number, -1, 1);
    
            switch($last)
            {
                case "1":
                $os = 'st';
                break;
    
                case "2":
                $os = 'nd';
                break;
    
                case "3":
                $os = 'rd';
                break;
    
                default:
                $os = 'th';
            }
        }
    
        /*** add super script ***/
        $os = $ss==0 ? $os : '<sup>'.$os.'</sup>';
    
        /*** return ***/
        return $number.$os;
    }
    ?> 
    
        6
  •  7
  •   WhiteHorse    9 年前

    简单而简单的答案是:

    $Day = 3; 
    echo date("S", mktime(0, 0, 0, 0, $Day, 0));
    
    //OUTPUT - rd
    
        7
  •  7
  •   iletras    8 年前

    我是为php4写的。 它一直在工作,很经济。

    function getOrdinalSuffix($number) {
        $number = abs($number) % 100;
        $lastChar = substr($number, -1, 1);
        switch ($lastChar) {
            case '1' : return ($number == '11') ? 'th' : 'st';
            case '2' : return ($number == '12') ? 'th' : 'nd';
            case '3' : return ($number == '13') ? 'th' : 'rd'; 
        }
        return 'th';  
    }
    
        8
  •  3
  •   Uzair Bin Nisar    12 年前

    一般来说,您可以使用它并调用 echo获取放置字符串(100);

    <?php
    function get_placing_string($placing){
        $i=intval($placing%10);
        $place=substr($placing,-2); //For 11,12,13 places
    
        if($i==1 && $place!='11'){
            return $placing.'st';
        }
        else if($i==2 && $place!='12'){
            return $placing.'nd';
        }
    
        else if($i==3 && $place!='13'){
            return $placing.'rd';
        }
        return $placing.'th';
    }
    ?>
    
        9
  •  3
  •   Chintan Thummar    10 年前

    您只需要应用给定的函数。

    function addOrdinalNumberSuffix($num) {
      if (!in_array(($num % 100),array(11,12,13))){
        switch ($num % 10) {
          // Handle 1st, 2nd, 3rd
          case 1:  return $num.'st';
          case 2:  return $num.'nd';
          case 3:  return $num.'rd';
        }
      }
      return $num.'th';
    }
    
        10
  •  2
  •   Community CDub    8 年前

    我做了一个不依赖php的函数 date(); 功能,因为它是不必要的,但也使它尽可能紧凑和简短,我认为是目前可能的。

    代码 :(共121字节)

    function ordinal($i) { // PHP 5.2 and later
      return($i.(($j=abs($i)%100)>10&&$j<14?'th':(($j%=10)>0&&$j<4?['st', 'nd', 'rd'][$j-1]:'th')));
    }
    

    下面是更紧凑的代码。

    其工作原理如下 :

    printf("The %s hour.\n",    ordinal(0));   // The 0th hour.
    printf("The %s ossicle.\n", ordinal(1));   // The 1st ossicle.
    printf("The %s cat.\n",     ordinal(12));  // The 12th cat.
    printf("The %s item.\n",    ordinal(-23)); // The -23rd item.
    

    关于这个函数的知识 :

    • 它处理与正整数相同的负整数,并保留符号。
    • 返回11、12、13、811th、812th、813th等 -青少年 数字如预期。
    • 它不检查小数,但会将它们留在原位(使用 floor($i) , round($i) ceil($i) 在最终申报表的开头)。
    • 你也可以添加 format_number($i) 在最后一个RETURN语句的开头获取一个逗号分隔的整数(如果显示的是数千、数百万等)。
    • 你可以把 $i 如果只想返回没有输入内容的序数后缀,则从返回语句的开头开始。

    这个函数的工作开始于2006年11月发布的PHP5.2,仅仅是因为使用了简短的数组语法。如果您之前有版本,请升级,因为您已经过时近十年了!如果失败,只需更换直列 ['st', 'nd', 'rd'] 临时变量包含 array('st', 'nd', 'rd'); .

    相同的功能(不返回输入),但为了更好地理解,我的简短功能的分解图:

    function ordinal($i) {
      $j = abs($i); // make negatives into positives
      $j = $j%100; // modulo 100; deal only with ones and tens; 0 through 99
    
      if($j>10 && $j<14) // if $j is over 10, but below 14 (so we deal with 11 to 13)
        return('th'); // always return 'th' for 11th, 13th, 62912th, etc.
    
      $j = $j%10; // modulo 10; deal only with ones; 0 through 9
    
      if($j==1) // 1st, 21st, 31st, 971st
        return('st');
    
      if($j==2) // 2nd, 22nd, 32nd, 582nd
        return('nd'); // 
    
      if($j==3) // 3rd, 23rd, 33rd, 253rd
        return('rd');
    
      return('th'); // everything else will suffixed with 'th' including 0th
    }
    

    代码更新 :

    下面是一个缩短了14个字节(总共107个字节)的修改版本:

    function ordinal($i) {
      return $i.(($j=abs($i)%100)>10&&$j<14?'th':@['th','st','nd','rd'][$j%10]?:'th');
    }
    

    或者尽可能短,短25个字节(总共96个字节):

    function o($i){return $i.(($j=abs($i)%100)>10&&$j<14?'th':@['th','st','nd','rd'][$j%10]?:'th');}
    

    使用最后一个函数,只需调用 o(121); 它的功能和我列出的其他功能完全一样。

    代码更新第2版 :

    Ben 我一起工作,把它减少了38个字节(总共83个字节):

    function o($i){return$i.@(($j=abs($i)%100)>10&&$j<14?th:[th,st,nd,rd][$j%10]?:th);}
    

    我们认为它不可能比这个短!然而,愿意被证明是错误的。:)

    希望大家都喜欢。

        11
  •  1
  •   Dan Dart    9 年前

    一个更短的版本,用于月份中的日期(最多31个),而不是使用mktime(),不需要pecl intl:

    function ordinal($n) {
        return (new DateTime('Jan '.$n))->format('jS');
    }
    

    或程序:

    echo date_format(date_create('Jan '.$n), 'jS');
    

    这当然有效,因为我选择的默认月份(1月)有31天。

    有趣的是,如果您在2月(或另一个没有31天的月)尝试它,它会在结束前重新启动:

    ...clip...
    31st
    1st
    2nd
    3rd
    

    所以您可以使用日期说明符最多计算本月的天数 t 在你的循环中:每月的天数。

        12
  •  1
  •   xyz    7 年前
    function ordinal($number){
    
        $last=substr($number,-1);
        if( $last>3 || $last==0 || ( $number >= 11 && $number <= 19 ) ){
          $ext='th';
        }else if( $last==3 ){
          $ext='rd';
        }else if( $last==2 ){
          $ext='nd';
        }else{
          $ext='st';
        }
        return $number.$ext;
      }
    
        13
  •  0
  •   mysticmo    9 年前

    在中找到答案 PHP.net

    <?php
    function ordinal($num)
    {
        // Special case "teenth"
        if ( ($num / 10) % 10 != 1 )
        {
            // Handle 1st, 2nd, 3rd
            switch( $num % 10 )
            {
                case 1: return $num . 'st';
                case 2: return $num . 'nd';
                case 3: return $num . 'rd';  
            }
        }
        // Everything else is "nth"
        return $num . 'th';
    }
    ?>
    
        14
  •  0
  •   Bilal Shareef    9 年前

    为了进一步简化Lacopo的答案,可以使用下面的函数,该函数使用substr()函数获取数字的最后一位,并将其用作$ends数组的索引。

    function get_ordinal($number)
    {
        $ends=array('th','st','nd','rd','th','th','th','th','th','th');
        $last_digit=substr($number, -1, 1);
        return $number.$ends[$last_digit];
    }
    

    编辑

    对于以11、12、13结尾的数字,我的上述功能似乎失败了,在发布答案时我没有注意到这些数字。所以使用拉科波的答案。

        15
  •  0
  •   Claire Matthews    6 年前

    这是另一个使用日期函数的非常短的版本。它适用于任何数字(不受月份天数限制),并考虑到*11*12*13不遵循*1*2*3格式。

    function getOrdinal($n)
    {
        return $n . date_format(date_create('Jan ' . ($n % 100 < 20 ? $n % 20 : $n % 10)), 'S');
    }
    
        16
  •  -1
  •   niksmac    11 年前

    我喜欢这个小片段

    <?php
    
      function addOrdinalNumberSuffix($num) {
        if (!in_array(($num % 100),array(11,12,13))){
          switch ($num % 10) {
            // Handle 1st, 2nd, 3rd
            case 1:  return $num.'st';
            case 2:  return $num.'nd';
            case 3:  return $num.'rd';
          }
        }
        return $num.'th';
      }
    
    ?>
    

    HERE