Nenhum produto encontrado nessa seleção.
Quando criamos um sistema que trabalha com números, normalmente imaginamos um tamanho máximo para o valor e – na maioria dos casos – esquecemos que aquele número máximo pode ser atingido um dia. Isso pode ocorrer com milhares de sistemas, desde um simples contador de visitas, até uma tabela e suas chaves primárias.
Sim! Eu sei que é muito difícil algo assim ocorrer, mas uma coisa é certa: em algum dia, um número muito grande deverá ser retornado e exibido na tela para o usuário, e não queremos exibir algo como 1000000000000000000000000 (um septilhão) para nosso usuário final.
Neste artigo, vou mostrar como contrair números gigantes com PHP utilizando os símbolos do Sistema Internacional de Unidades, ou seja, 1000000000000000000000000 se tornará 1Y.
Então vamos lá.
Sistema Internacional de Unidades
No Sistema Internacional de Unidades temos a seguinte tabela demonstrando os números.
1000m | 10n | Prefixo | Símbolo | Desde | Escala curta | Escala longa | Equivalente numérico |
---|---|---|---|---|---|---|---|
10008 | 1024 | yotta (iota) | Y | 1991 | Septilhão | Quadrilião | 1 000 000 000 000 000 000 000 000 |
10007 | 1021 | zetta (zeta) | Z | 1991 | Sextilhão | Milhar de trilião | 1 000 000 000 000 000 000 000 |
10006 | 1018 | exa | E | 1975 | Quintilhão | Trilião | 1 000 000 000 000 000 000 |
10005 | 1015 | peta | P | 1975 | Quadrilhão | Milhar de bilião | 1 000 000 000 000 000 |
10004 | 1012 | tera | T | 1960 | Trilhão | Bilião | 1 000 000 000 000 |
10003 | 109 | giga | G | 1960 | Bilhão | Milhar de milhão | 1 000 000 000 |
10002 | 106 | mega | M | 1960 | Milhão | Milhão | 1 000 000 |
10001 | 103 | quilo | k | 1795 | Mil | Milhar | 1 000 |
10002/3 | 102 | hecto | h | 1795 | Cem | Centena | 100 |
10001/3 | 101 | deca | da | 1795 | Dez | Dezena | 10 |
10000 | 100 | nenhum | nenhum | Unidade | Unidade | 1 | |
1000-1/3 | 10−1 | deci | d | 1795 | Décimo | Décimo | 0,1 |
1000-2/3 | 10−2 | centi | c | 1795 | Centésimo | Centésimo | 0,01 |
1000-1 | 10−3 | mili | m | 1795 | Milésimo | Milésimo | 0,001 |
1000-2 | 10−6 | micro | µ | 1960 | Milionésimo | Milionésimo | 0,000 001 |
1000-3 | 10−9 | nano | n | 1960 | Bilionésimo | Milésimo de milionésimo | 0,000 000 001 |
1000-4 | 10−12 | pico | p | 1960 | Trilionésimo | Bilionésimo | 0,000 000 000 001 |
1000-5 | 10−15 | femto (fento) | f | 1964 | Quadrilionésimo | Milésimo de bilionésimo | 0,000 000 000 000 001 |
1000-6 | 10−18 | atto (ato) | a | 1964 | Quintilionésimo | Trilionésimo | 0,000 000 000 000 000 001 |
1000-7 | 10−21 | zepto | z | 1991 | Sextilionésimo | Milésimo de trilionésimo | 0,000 000 000 000 000 000 001 |
1000-8 | 10−24 | yocto (iocto) | y | 1991 | Septilionésimo | Quadrilionésimo | 0,000 000 000 000 000 000 000 001 |
Vamos criar uma função para contrair números baseada na coluna símbolos acima (apenas números maiores ou iguais a mil).
Função para contrair números gigantes com PHP
A ideia é pegar os números e dividir pelo seu valor correspondente.
Por exemplo: Se o número for maior que 999 – 1000 no caso – dividimos o mesmo por 1000 e teremos o resultado 1. Por fim adicionaremos o símbolo correspondente, que nesse caso é o k (kilo). Como resultado teremos 1000 = 1k.
Não podemos fazer a conta diretamente, pois, o PHP só vai suportar um número inteiro com o valor máximo igual ao valor da constante PHP_INT_MAX, então usaremos a função bcdiv, que divide dois números de precisão arbitrária.
Veja como fica:
<?php /** * Função para contrair números muito grandes * * @param string $number O número * @param int $decimals Quantos números decimais a serem exibidos * @param bool $int_only Remove todos os números decimais */ function prettify_numbers ( $number = '0', $decimals = 2, $int_only = false ) { // O número (que na verdade deve ser uma string) $number = (string)$number; // O símbolo $simbol = null; // yotta: 1000000000000000000000000 if ( $number > '99999999999999999999999' ) { $number = bcdiv( $number, '1000000000000000000000000', $decimals); $simbol = 'Y'; } // Zetta: 1000000000000000000000 elseif ( $number > '999999999999999999999' ) { $number = bcdiv( $number, '1000000000000000000000', $decimals); $simbol = 'Z'; } // Exa : 1000000000000000000 elseif ( $number > '999999999999999999' ) { $number = bcdiv( $number, '1000000000000000000', $decimals); $simbol = 'E'; } // Peta : 1000000000000000 elseif ( $number > '999999999999999' ) { $number = bcdiv( $number, '1000000000000000', $decimals); $simbol = 'P'; } // Tera : 1000000000000 elseif ( $number > '999999999999' ) { $number = bcdiv( $number, '1000000000000', $decimals); $simbol = 'T'; } // Tera : 1000000000 elseif ( $number > '999999999' ) { $number = bcdiv( $number, '1000000000', $decimals); $simbol = 'G'; } // Mega : 1000000 elseif ( $number > '999999' ) { $number = bcdiv( $number, '1000000', $decimals); $simbol = 'M'; } // Kilo : 1000 elseif ( $number > '999' ) { $number = bcdiv( $number, '1000', $decimals); $simbol = 'k'; } // Retorna apenas o número inteiro if ( $int_only ) return (int)$number . $simbol; // Retorna o número e o símbolo return $number . $simbol; } ?>
Na função acima teremos 3 parâmetros:
- $numero – O número deverá ser enviado em formato de string, ou seja, entre aspas;
- $decimals – O número de casas decimais que deseja exibir;
- $int_only – Se verdadeiro, remove todas as casas decimais;
Então para utilizar a função, faríamos o seguinte:
// Executa a função echo prettify_numbers( '1995', 2 );
O que retornaria: 1.99k
Vamos a um número gigantesco:
// Executa a função echo prettify_numbers( '199554211125482', 2 );
Retorna: 199.55T
Quer ainda maior? Vejamos:
// Executa a função echo prettify_numbers( '19955421112548254545418455487', 2 );
Daria: 19955.42Y
O último parâmetro é meio que um enfeite, pois, você pode remover os decimais apenas modificando o segundo parâmetro para zero (0). Veja:
// Executa a função echo prettify_numbers( '199554218455487', 0 );
Geraria: 199T.
Concluindo
Esse tipo de sistema gera um valor aproximado, ou seja, quando maior o número, menor precisão teremos. Utilize apenas para contar algo que não precisa de muita precisão.
Em caso de dúvidas, não hesite em comentar.