Files
archived-doc-pt-br/language/types/float.xml
2025-08-23 16:58:14 -03:00

193 lines
6.4 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: e587d0655e426f97b3fcb431453da5030e743b23 Maintainer: leonardolara Status: ready --><!-- CREDITS: felipe,ae,fabioluciano,geekcom,lisaldo,lhsazevedo,leonardolara -->
<sect1 xml:id="language.types.float" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Números de ponto flutuante</title>
<para>
Números de ponto flutuante (também conhecidos como "floats", "doubles" ou "números reais"), podem ser
especificados utilizando qualquer uma das seguintes sintaxes:
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$a = 1.234;
$b = 1.2e3;
$c = 7E-10;
$d = 1_234.567; // a partir do PHP 7.4.0
?>
]]>
</programlisting>
</informalexample>
<para>
Formalmente a partir do PHP 7.4.0 (anteriormente, sublinhados não eram permitidos):
</para>
<informalexample>
<programlisting>
<![CDATA[
LNUM [0-9]+(_[0-9]+)*
DNUM ({LNUM}?"."{LNUM}) | ({LNUM}"."{LNUM}?)
EXPONENT_DNUM (({LNUM} | {DNUM}) [eE][+-]? {LNUM})
]]>
</programlisting>
</informalexample>
<para>
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).
</para>
<warning xml:id="warn.float-precision">
<title>Precisão de números de ponto flutuante</title>
<para>
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.
</para>
<para>
Além disso, números racionais que têm representação exata em números
em base 10, como <literal>0.1</literal> ou
<literal>0.7</literal>, 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, <literal>floor((0.1+0.7)*10)</literal> normalmente
retornará <literal>7</literal>, em vez do resultado esperado <literal>8</literal>,
porque a representação interna final será algo como
<literal>7.9999999999999991118...</literal>.
</para>
<para>
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 <link linkend="ref.bc">funções matemáticas de precisão arbitrária</link>
e as funções <link linkend="ref.gmp">gmp</link> estão disponíveis.
</para>
<para>
Para uma explicação "simples" dessa questão, veja o <link xlink:href="&url.floating.point.guide;">guia sobre ponto flutuante</link>,
que também tem o título alternativo de "Porque meus números não somam direito?".
</para>
</warning>
<sect2 xml:id="language.types.float.casting">
<title>Convertendo para float</title>
<sect3 xml:id="language.types.float.casting.from-string">
<title>A partir de strings</title>
<simpara>
Se a string é
<link linkend="language.types.numeric-strings">numérica</link>
ou começa numérica então ela irá resolver para o
valor float correspondente, do contrário ela é convertida em zero
(<literal>0</literal>).
</simpara>
</sect3>
<sect3 xml:id="language.types.float.casting.from-other">
<title>A partir de outros tipos</title>
<para>
Para valores de outros tipos, a conversão é realizada convertendo o
valor para <type>int</type> primeiro e em seguida para <type>float</type>. Veja
<link linkend="language.types.integer.casting">Convertendo para inteiro</link>
para mais informações.
</para>
<note>
<para>
Como certos tipos têm comportamento indefinido ao converter para
<type>int</type>, este também é o caso ao converter para
<type>float</type>.
</para>
</note>
</sect3>
</sect2>
<sect2 xml:id="language.types.float.comparison">
<title>Comparando floats</title>
<para>
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>
<para>
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.
</para>
<para>
<varname>$a</varname> e <varname>$b</varname> serão consideradas iguais
até o 5º dígito de precisão.
</para>
<example>
<title>Comparando números de ponto flutuante</title>
<programlisting role="php">
<![CDATA[
<?php
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;
if (abs($a - $b) < $epsilon) {
echo "iguais";
}
?>
]]>
</programlisting>
</example>
</sect2>
<sect2 xml:id="language.types.float.nan">
<title>NaN</title>
<para>
Algumas operações numéricas podem resultar em valores representados pela constante
<constant>NAN</constant>. 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, com exceção de &true;, terá
como resultado &false;.
</para>
<para>
Como o <constant>NAN</constant> representa um resultado irrepresentável,
<constant>NAN</constant> não deve ser comparado com outros valores, incluindo
ele mesmo, em vez disso, deve-se checá-lo utilizando a função <function>is_nan</function>.
</para>
</sect2>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->