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.

1000m10nPrefixoSímboloDesdeEscala curtaEscala longaEquivalente numérico
100081024yotta (iota)Y1991SeptilhãoQuadrilião1 000 000 000 000 000 000 000 000
100071021zetta (zeta)Z1991SextilhãoMilhar de trilião1 000 000 000 000 000 000 000
100061018exaE1975QuintilhãoTrilião1 000 000 000 000 000 000
100051015petaP1975QuadrilhãoMilhar de bilião1 000 000 000 000 000
100041012teraT1960TrilhãoBilião1 000 000 000 000
10003109gigaG1960BilhãoMilhar de milhão1 000 000 000
10002106megaM1960MilhãoMilhão1 000 000
10001103quilok1795MilMilhar1 000
10002/3102hectoh1795CemCentena100
10001/3101decada1795DezDezena10
10000100nenhumnenhumUnidadeUnidade1
1000-1/310−1decid1795DécimoDécimo0,1
1000-2/310−2centic1795CentésimoCentésimo0,01
1000-110−3milim1795MilésimoMilésimo0,001
1000-210−6microµ1960MilionésimoMilionésimo0,000 001
1000-310−9nanon1960BilionésimoMilésimo de milionésimo0,000 000 001
1000-410−12picop1960TrilionésimoBilionésimo0,000 000 000 001
1000-510−15femto (fento)f1964QuadrilionésimoMilésimo de bilionésimo0,000 000 000 000 001
1000-610−18atto (ato)a1964QuintilionésimoTrilionésimo0,000 000 000 000 000 001
1000-710−21zeptoz1991SextilionésimoMilésimo de trilionésimo0,000 000 000 000 000 000 001
1000-810−24yocto (iocto)y1991SeptilionésimoQuadrilionésimo0,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.