Veja minha resposta aqui. stackoverflow.com/questions/69262/… Essa pergunta era para .NET, mas eu respondi com uma solução PHP, por isso deve ajudá-lo.
nickf
A única maneira de pensar em fazer isso é ter uma instrução if subindo para cada número que você possa ter, IE, se (1) então "st" elseif (2) então "nd" etc etc if (23000) then " nd ". É um problema se você tiver grandes números, mas puder escrever um programa para escrever o código para você, ele poderá fazer um loop em todos os números que imprimem os ifs para você copiar + colar no seu código.
Tom Gullen
2
@ Tom, uma tabela de pesquisa pode ser melhor, apenas inicialize-a com os valores 23000 e obtenha o valor no índice n, onde n é o número que você deseja que o ordinal.
precisa
2
Coronel Shrapnel. você pode brilhante, mas não todos. qualquer forma obrigado por mostrar interesse na minha pergunta
Arca
@ John, idéia muito, muito inteligente, seria muito rápido para acessar, bem como cada índice representa o número que você está procurando.
Embora um pouco difícil de entender a princípio, agora acho que melhor representa como o sistema de sufixos ordinais funciona para o inglês.
erisco
5
Eu gosto da sua solução. Além disso, se você preferir não para gerar 0 modificar a última linha a ser$abbreviation = ($number)? $number. $ends[$number % 10] : $number;
Gavin Jackson
1
@GavinJackson sua adição a esta excelente solução realmente me ajudou (+1). Você poderia me explicar o que está acontecendo no cálculo? Eu quero entender. Felicidades! EDIT: Encontrado uma resposta: operador condicional
Andrew Fox
Desculpe, tive que quebrar os 111 votos a 112: D Tornou uma função no Delphi junto com um aplicativo de demonstração: pastebin.com/wvmz1CHY
Jerry Dodge
1
@HafezDivandari - você tem certeza? Apenas testado com 7.1.19 e parece funcionar bem
Você sabe se é possível obter o número ordinal em forma de palavra? ou seja, primeiro, segundo, terceiro, etc. em vez de primeiro, segundo, terceiro ...
its_me 16/10
@jeremy Quando tentei usar o NumberFormatter, ele sempre gera um erro NumberFomatter file not found. Como você resolveu isso?
Jhnferraris
1
@Jhn você tem que instalar a extensãoapt-get install php5-intl
Aley
@Aley eu vejo. O Yii possui um formatador incorporado que estamos usando no momento. heh
jhnferraris
20
Isso pode ser realizado em uma única linha, aproveitando a funcionalidade semelhante nas funções de data / hora internas do PHP. Eu humildemente submeto:
Solução:
function ordinalSuffix( $n ){return date('S',mktime(1,1,1,1,((($n>=10)+($n>=20)+($n==0))*10+ $n%10)));}
Explicação detalhada:
A date()função interna possui lógica de sufixo para lidar com os cálculos do enésimo dia do mês. O sufixo é retornado quando Sé fornecido na string de formato:
date('S',?);
Desde date()requer um timestamp (para ?cima), nós vamos passar o nosso inteiro $ncomo o dayparâmetro para mktime()e uso manequim valores de 1para o hour, minute, second, e month:
date('S', mktime(1,1,1,1, $n ));
Na verdade, isso falha normalmente nos valores fora do intervalo de um dia do mês (ou seja $n > 31), mas podemos adicionar uma lógica embutida simples ao limite de $n29:
Conforme observado por @donatJ, o acima falhou acima de 100 (por exemplo, "111st"), pois as >=20verificações estão sempre retornando verdadeiras. Para redefini-las a cada século, adicionamos um filtro à comparação:
Eu gosto dessa abordagem, mas, infelizmente, ela não funciona :-( o 30º sai como o 30º. O 40º sai como o 40º etc. etc.
Flukey
1
Sim, desculpe-me. Quando li a pergunta que pensei, ei, isso deve ser possível por uma única linha de código. E eu apenas digitei. Como você vê nas minhas edições, estou melhorando. Após a terceira edição agora, acho que está bem feito. Pelo menos todos os números de 1 a 150 são impressos na tela.
Paulo
Parece bom até 500! (ainda não o testei). Bom trabalho! :-)
Não diz nada sobre datas na pergunta tho. I upvoted qualquer maneira - é uma solução rápida e simples quando você sabe que o intervalo de números vai ser <32
cronoklee
8
Eu escrevi isso para PHP4. Está funcionando bem e é bem econômico.
Eu criei uma função que não depende da date();função do PHP, pois ela não é necessária, mas também a tornei tão compacta e tão curta quanto eu acho que é atualmente possível.
O código : (121 bytes no total)
function ordinal($i){// PHP 5.2 and laterreturn($i.(($j=abs($i)%100)>10&&$j<14?'th':(($j%=10)>0&&$j<4?['st','nd','rd'][$j-1]:'th')));}
Código mais compacto abaixo.
Funciona da seguinte maneira :
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.
Coisas a saber sobre esta função :
Ele lida com números inteiros negativos da mesma forma que números inteiros positivos e mantém o sinal.
Retorna 11º, 12º, 13º, 811º, 812º, 813º etc. para os números -14 , conforme o esperado.
Ele não verifica decimais, mas vai deixá-los no lugar (uso floor($i), round($i)ou ceil($i)no início da instrução de retorno final).
Você também pode adicionar format_number($i)no início da declaração de retorno final para obter um número inteiro separado por vírgula (se estiver exibindo milhares, milhões, etc.).
Você pode remover o $iinício da declaração de retorno apenas se desejar retornar o sufixo ordinal sem o que você inseriu.
Esta função funciona a partir do PHP 5.2, lançado em novembro de 2006, apenas por causa da sintaxe curta da matriz. Se você possui uma versão anterior a essa atualização, atualize-a porque está quase uma década desatualizada! Caso contrário, basta substituir a linha ['st', 'nd', 'rd']por uma variável temporária contendoarray('st', 'nd', 'rd'); .
A mesma função (sem retornar a entrada), mas uma visão explodida da minha função curta para melhor entendimento:
function ordinal($i){
$j = abs($i);// make negatives into positives
$j = $j%100;// modulo 100; deal only with ones and tens; 0 through 99if($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 9if($j==1)// 1st, 21st, 31st, 971streturn('st');if($j==2)// 2nd, 22nd, 32nd, 582ndreturn('nd');// if($j==3)// 3rd, 23rd, 33rd, 253rdreturn('rd');return('th');// everything else will suffixed with 'th' including 0th}
Atualização de código :
Aqui está uma versão modificada que é 14 bytes inteiros mais curtos (total de 107 bytes):
function ordinal($i){return $i.(($j=abs($i)%100)>10&&$j<14?'th':@['th','st','nd','rd'][$j%10]?:'th');}
Ou, o mais curto possível, sendo 25 bytes mais curtos (total de 96 bytes):
function o($i){return $i.(($j=abs($i)%100)>10&&$j<14?'th':@['th','st','nd','rd'][$j%10]?:'th');}
Com esta última função, basta chamar o(121);e ele fará exatamente o mesmo que as outras funções que listei.
Atualização de código # 2 :
Ben e eu trabalhamos juntos e reduzimos em 38 bytes (83 bytes no total):
function o($i){return$i.@(($j=abs($i)%100)>10&&$j<14?th:[th,st,nd,rd][$j%10]?:th);}
Não achamos que possa ficar mais curto que isso! Disposto a ser provado errado, no entanto. :)
Aqui está outra versão muito curta, usando as funções de data. Funciona para qualquer número (sem restrição de dias do mês) e leva em consideração que * 11 * 12 * 13 não segue o formato * 1 * 2 * 3.
Não tenho muita certeza do que essa resposta oferece, além da resposta de ChintanThummar. Bem, isso sugere que ChintanThummar fez uma violação de direitos autorais, a menos que ele escreveu o código na sua fonte ...
Respostas:
da wikipedia :
Onde
$number
está o número que você deseja escrever. Funciona com qualquer número natural.Como uma função:
fonte
$abbreviation = ($number)? $number. $ends[$number % 10] : $number;
O PHP possui funcionalidade incorporada para isso . Ele até lida com internacionalização!
Note que esta funcionalidade está disponível apenas no PHP 5.3.0 e posterior.
fonte
NumberFomatter file not found
. Como você resolveu isso?apt-get install php5-intl
Isso pode ser realizado em uma única linha, aproveitando a funcionalidade semelhante nas funções de data / hora internas do PHP. Eu humildemente submeto:
Solução:
Explicação detalhada:
A
date()
função interna possui lógica de sufixo para lidar com os cálculos do enésimo dia do mês. O sufixo é retornado quandoS
é fornecido na string de formato:Desde
date()
requer um timestamp (para?
cima), nós vamos passar o nosso inteiro$n
como oday
parâmetro paramktime()
e uso manequim valores de1
para ohour
,minute
,second
, emonth
:Na verdade, isso falha normalmente nos valores fora do intervalo de um dia do mês (ou seja
$n > 31
), mas podemos adicionar uma lógica embutida simples ao limite de$n
29:O único valor positivo( Maio de 2017 ), isso falha$n == 0
, mas isso é facilmente corrigido adicionando 10 nesse caso especial:Atualização, maio de 2017
Conforme observado por @donatJ, o acima falhou acima de 100 (por exemplo, "111st"), pois as
>=20
verificações estão sempre retornando verdadeiras. Para redefini-las a cada século, adicionamos um filtro à comparação:Basta envolvê-lo em uma função por conveniência e pronto!
fonte
Aqui está uma frase:
Provavelmente a solução mais curta. Obviamente, pode ser envolvido por uma função:
Atenciosamente, Paul
EDIT1: Correção do código de 11 a 13.
EDIT2: Correção de código para 111, 211, ...
EDIT3: Agora também funciona corretamente para múltiplos de 10.
fonte
de http://www.phpro.org/examples/Ordinal-Suffix.html
fonte
Resposta simples e fácil será:
fonte
Eu escrevi isso para PHP4. Está funcionando bem e é bem econômico.
fonte
você só precisa aplicar uma determinada função.
fonte
Genericamente, você pode usar isso e chamar echo get_placing_string (100);
fonte
Eu criei uma função que não depende da
date();
função do PHP, pois ela não é necessária, mas também a tornei tão compacta e tão curta quanto eu acho que é atualmente possível.O código : (121 bytes no total)
Código mais compacto abaixo.
Funciona da seguinte maneira :
Coisas a saber sobre esta função :
floor($i)
,round($i)
ouceil($i)
no início da instrução de retorno final).format_number($i)
no início da declaração de retorno final para obter um número inteiro separado por vírgula (se estiver exibindo milhares, milhões, etc.).$i
início da declaração de retorno apenas se desejar retornar o sufixo ordinal sem o que você inseriu.Esta função funciona a partir do PHP 5.2, lançado em novembro de 2006, apenas por causa da sintaxe curta da matriz. Se você possui uma versão anterior a essa atualização, atualize-a porque está quase uma década desatualizada! Caso contrário, basta substituir a linha
['st', 'nd', 'rd']
por uma variável temporária contendoarray('st', 'nd', 'rd');
.A mesma função (sem retornar a entrada), mas uma visão explodida da minha função curta para melhor entendimento:
Atualização de código :
Aqui está uma versão modificada que é 14 bytes inteiros mais curtos (total de 107 bytes):
Ou, o mais curto possível, sendo 25 bytes mais curtos (total de 96 bytes):
Com esta última função, basta chamar
o(121);
e ele fará exatamente o mesmo que as outras funções que listei.Atualização de código # 2 :
Ben e eu trabalhamos juntos e reduzimos em 38 bytes (83 bytes no total):
Não achamos que possa ficar mais curto que isso! Disposto a ser provado errado, no entanto. :)
Espero que todos gostem.
fonte
abs()
com módulo%
abs();
remove o sinal negativo que é o que eu precisava.Uma versão ainda mais curta para datas no mês (até 31) em vez de usar mktime () e não exigir pecl intl:
ou processualmente:
Isso funciona, é claro, porque o mês padrão que escolhi (janeiro) tem 31 dias.
Curiosamente, se você tentar com fevereiro (ou outro mês sem 31 dias), ele será reiniciado antes do final:
para que você possa contar até os dias deste mês com o especificador de data
t
em seu loop: número de dias no mês.fonte
fonte
Encontrei uma resposta no PHP.net
fonte
Aqui está outra versão muito curta, usando as funções de data. Funciona para qualquer número (sem restrição de dias do mês) e leva em consideração que * 11 * 12 * 13 não segue o formato * 1 * 2 * 3.
fonte
Eu gosto deste pequeno trecho
AQUI
fonte