Números de ponto flutuante (também conhecidos como "floats", "doubles" ou "números reais"), podem ser especificados utilizando qualquer uma das seguintes sintaxes:
<?php
$a = 1.234;
$b = 1.2e3;
$c = 7E-10;
?>
Formalmente:
LNUM [0-9]+ DNUM ([0-9]*[\.]{LNUM}) | ({LNUM}[\.][0-9]*) EXPONENT_DNUM [+-]?(({LNUM} | {DNUM}) [eE][+-]? {LNUM})
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).
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?".
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.
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.
$a e $b serão consideradas iguais até o 5º dígito de precisão.
<?php
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;
if(abs($a-$b) < $epsilon) {
echo "iguais";
}
?>
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
si mesmo, em vez disso, deve-se checá-lo utilizando a função is_nan().