Números de ponto flutuante
Números de ponto flutuante (também conhecidos como "floats", "doubles" ou "números reais"), podem ser
especificados utilizando qualquer uma das seguintes sintaxes:
Formalmente a partir do PHP 7.4.0 (anteriormente, sublinhados não eram permitidos):
O tamanho de um número de ponto flutuante depende da plataforma, sendo o máximo de ~1.8e308 com
precisão de 14 dígitos decimais um valor comum (número de 64 bits no formato
IEEE).
Aviso
Precisão de números de ponto flutuante
Números de ponto flutuante tem precisão limitada. Embora dependa do sistema,
o PHP geralmente utiliza o formato de precisão dupla do IEEE 754, que
trará uma precisão máxima devida a arredondamentos da ordem de 1.11e-16.
Operações matemáticas incomuns poderão ocasionar erros maiores, e, claro,
a propagação de erros deve ser considerada quando várias operações
forem realizadas.
Além disso, números racionais que tem representação exata em números
em base 10, como 0.1
ou
0.7
, não possuem representação exata em ponto flutuante
na base 2, o formato utilizado internamente, não importando o tamanho
da mantissa. Portanto não existe conversão para o formato interno sem
uma pequena perda de precisão. Isso pode ocasionar resultados
confusos: por exemplo, floor((0.1+0.7)*10)
normalmente
retornará 7
, em vez do resultado esperado 8
,
porque a representação interna final será algo como
7.9999999999999991118...
.
Então, nunca confie em resultados com números de ponto flutuante até a última casa, e
nunca compare números de ponto flutuante em igualdades. Se você realmente
precisar de alta precisão, você pode utilizar as funções matemáticas de precisão arbitrária
e as funções gmp estão disponíveis.
Para uma explicação "simples" dessa questão, veja o » guia sobre ponto flutuante,
que também tem o título alternativo de "Porque meus números não somam direito?".
Convertendo para float
Para informações sobre a conversão de strings para float,
veja a seção Conversão de
Strings para números. Para valores de outros tipos, o valor é primeiro
convertido para inteiro e então para
float. Veja a seção
Convertendo
para inteiros para mais informações. No PHP 5, um aviso é emitido se você tentar converter um
object para um float.
Comparando floats
Como notado acima, testar números de ponto flutuante com igualdade é
problemático, por causa da maneira como são representados internamente. Entretanto
existem maneiras de fazer comparações com números de ponto flutuante que
contornam essas limitações.
Para testar números de ponto flutuante, utilize um "valor de erro máximo"
na comparação utilizada. Esse valor é também chamado de epsilon,
ou unidade de erro, e deve ser a diferença mínima aceitável no resultado dos cálculos.
NaN
Algumas operações numéricas podem resultar em valores representados pela constante
NAN
. Esse resultado representa um valor desconhecido
ou não representável nos cálculos de ponto flutuante. Qualquer comparação frouxa
ou restrita deste valor com qualquer outro, inclusive ele mesmo, terá
como resultado false
.
Como o NAN
representa um resultado irrepresentável,
NAN
não deve ser comparado com outros valores, incluindo
ele mesmo, em vez disso, deve-se checá-lo utilizando a função is_nan().