PHP에서 서 수가 붙은 숫자 표시


149

다음과 같이 숫자를 표시하고 싶습니다

  • 1을 1로,
  • 2를 2로,
  • ...,
  • 150은 150입니다.

코드에서 각 숫자의 올바른 서수 (st, nd, rd 또는 th)를 어떻게 찾습니까?


2
여기 내 대답을 참조하십시오. stackoverflow.com/questions/69262/… 그 질문은 .NET에 대한 것이지만 PHP 솔루션으로 답변했기 때문에 도움이 될 것입니다.
nickf

내가 이것을 생각할 수있는 유일한 방법은 당신이 할 수있는 모든 숫자에 대해 if 문이 올라가는 것입니다. nd ". 큰 숫자가 있으면 문제가되지만 코드를 작성하는 프로그램을 작성할 수 있으며 코드에 복사 + 붙여 넣기 위해 if를 인쇄하는 모든 숫자를 반복 할 수 있습니다.
톰 굴렌

2
@Tom, 조회 테이블이 더 좋을 수도 있습니다 .23000 값으로 초기화하고 인덱스 n에서 값을 얻으십시오. 여기서 n은 서수를 원하는 숫자입니다.
John Boker

2
콜랩 대령. 당신은 훌륭하지만 전부는 아닙니다. 내 질문에 관심을 보여 주셔서 감사합니다
ArK

@ John, 매우 영리한 아이디어입니다. 액세스하는 것이 매우 빠르며 각 색인은 찾고있는 숫자를 나타냅니다.
톰 굴렌

답변:


283

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);

처음에는 이해하기가 조금 어렵지만 서수 시스템이 영어에서 어떻게 작동하는지 가장 잘 나타내고 있다고 생각합니다.
erisco

6
나는 당신의 해결책을 좋아합니다. 또한 0 번째 를 생성하지 않으려면 마지막 줄을 다음과 같이 수정하십시오.$abbreviation = ($number)? $number. $ends[$number % 10] : $number;
Gavin Jackson

1
@GavinJackson이 우수한 솔루션에 추가하면 정말 도움이됩니다 (+1). 계산에서 무슨 일이 일어나고 있는지 설명해 주시겠습니까? 이해하고 싶습니다. 건배! 편집 : 답을 찾았습니다 : 조건부 연산자
Andrew Fox

죄송합니다, 111 투표 수 112로 깨뜨 렸습니다 : D 델파이에서 데모 앱과 함께 함수로 만들었습니다. pastebin.com/wvmz1CHY
Jerry Dodge

1
@HafezDivandari-확실합니까? 그냥 7.1.19에서 테스트하고 잘 작동 것 같다
Iacopo

142

PHP에는이 기능이 내장되어 있습니다 . 국제화도 처리합니다!

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

이 기능은 PHP 5.3.0 이상에서만 사용할 수 있습니다.


15
또한 PECL intl> = 1.0.0이 필요합니다.
rymo

4
단어 형태의 서수를 얻을 수 있는지 알고 있습니까? 즉, 첫 번째, 두 번째, 세 번째, 등 대신 1, 2, 3의 ...
its_me

@jeremy NumberFormatter를 사용하려고하면 항상 오류가 발생합니다 NumberFomatter file not found. 이 문제를 어떻게 해결 했습니까?
jhnferraris 2013

1
@Jhn 확장 프로그램을 설치해야합니다apt-get install php5-intl
Aley

@Aley 알겠습니다. Yii에는 현재 사용중인 포맷터가 내장되어 있습니다. heh
jhnferraris

20

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' , ? );

때문에 date()타임 스탬프를 (을위한 필요 ?이상), 우리는 우리의 정수를 통과 할 것이다 $n는 AS day에 대한 매개 변수 mktime()의 값 더미 및 사용 1에 대한 hour, minute, second, 및 month:

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

이것은 실제로 달의 범위를 벗어난 값 (예 :)에서 정상적으로 실패 $n > 31하지만 $n29 에서 캡 을 하기 위해 간단한 인라인 논리를 추가 할 수 있습니다 .

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에 의해 관찰 된 바와 같이, >=20검사가 항상 참을 반환하기 때문에 위의 100 이상 (예 : "111st")에 실패 합니다. 모든 세기를 재설정하기 위해 비교에 필터를 추가합니다.

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

편의를 위해 기능으로 감싸면됩니다.


14

다음은 하나의 라이너입니다.

$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까지의 코드 수정.

EDIT2 : 111, 211, ...에 대한 코드 수정

EDIT3 : 이제 10의 배수에도 올바르게 작동합니다.


나는이 접근법을 좋아하지만 아아, 그것은 작동하지 않습니다 :-( 30은 30으로 나옵니다. 40은 40으로 나옵니다.
Flukey

1
그래, 미안 내가 생각한 질문을 읽을 때, 이것은 한 줄의 코드로 가능해야합니다. 그리고 방금 입력했습니다. 편집 한 내용에서 알 수 있듯이 개선 중입니다. 세 번째 편집 후에는 꽤 끝났다고 생각합니다. 적어도 1에서 150까지의 모든 숫자가 화면에 멋지게 인쇄됩니다.
Paul

500까지 좋아 보인다! (그 이상으로 테스트하지는 않았습니다). 잘 했어! :-)
Flukey 2018 년

13

에서 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;
}
?> 

9

간단하고 쉬운 답변은 다음과 같습니다.

$Day = 3; 
echo date("S", mktime(0, 0, 0, 0, $Day, 0));

//OUTPUT - rd

질문에 날짜에 대해서는 아무 말도하지 않습니다. 어쨌든 upvoted - 당신이 수의 범위는 <32가 될 것입니다 알고는 빠르고 간단한 해결책이다
cronoklee

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';  
}

쿠마르 비서, 당신은 좀 더 확장 / 설명 / 설명 할 수 있습니까? Tks!
iletras

4

당신은 주어진 기능을 적용해야합니다.

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';
}

3

일반적으로이를 사용하고 echo get_placing_string (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';
}
?>

2

date();필연적으로 PHP 기능 에 의존하지 않는 기능을 만들었지 만 현재 가능한 한 작고 짧게 만들었습니다.

코드 : (총 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.

이 기능에 대해 알아야 할 사항 :

  • 양의 정수와 동일한 음의 정수를 처리하고 부호를 유지합니다.
  • 예상대로 -teen 숫자에 대해 11, 12, 13, 811, 812, 813 등을 반환 합니다.
  • 그것은 소수를 확인하지 않습니다 만, (사용 장소에 떠나 floor($i), round($i)또는 ceil($i)최종 return 문의 시작 부분에).
  • format_number($i)최종 반환 문의 시작 부분에 쉼표로 구분 된 정수 (수천, 수백만 등을 표시하는 경우)를 얻기 위해 추가 할 수도 있습니다 .
  • $i입력 한 내용없이 서수 접미사 만 반환하려는 경우 return 문의 시작 부분에서를 제거 할 수 있습니다 .

이 함수는 짧은 배열 구문 때문에 2006 년 11 월에 릴리스 된 PHP 5.2부터 시작합니다. 이전 버전이 있다면 거의 10 년이 지났으므로 업그레이드하십시오! 실패하면 인라인 ['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);}

우리는 이것이 이것보다 짧을 수 있다고 생각하지 않습니다! 그러나 잘못 될 것입니다. :)

모두 즐기시기 바랍니다.


abs()모듈러스와 함께 사용할 필요는 없습니다.%
99 문제 – 구문은 1

모듈로에만 의존하면 여전히 음의 부호가 남습니다. abs();내가 필요한 음수 부호를 제거합니다.
nxasdf

1

mktime ()을 사용하지 않고 pecl intl을 요구하지 않고 월의 날짜 (최대 31 개)에 대한 더 짧은 버전 :

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루프 의 날짜 지정자를 사용하여이 달의 일 수를 계산할 수 있습니다. 월의 일 수입니다.


1
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;
  }

0

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';
}
?>

0

날짜 함수를 사용하는 또 다른 매우 짧은 버전이 있습니다. 임의의 수 (월의 일로 제한되지 않음)에 대해 작동하며 * 11 번째 * 12 번째 * 13 번째는 * 1 번째 * 2 번째 * 3 번째 형식을 따르지 않습니다.

function getOrdinal($n)
{
    return $n . date_format(date_create('Jan ' . ($n % 100 < 20 ? $n % 20 : $n % 10)), 'S');
}

-1

나는이 작은 발췌문을 좋아한다

<?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';
  }

?>

여기


1
ChintanThummar의 답변 외에도이 답변이 무엇을 제공하는지 잘 모르겠습니다. 음, 그것은 당신의 소스에서 코드를 작성하지 않는 한 ChintanThummar가 저작권을 위반했다고 암시합니다 ...
Andreas Rejbrand
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.