Files
php-doc-ru/language/types/float.xml
Sergey Panteleev cfbbacb469 Исправление определений и терминов
- Исправлено дублирование терминов - плавающая точка

Closes GH-19
2021-02-15 15:39:58 +03:00

197 lines
9.2 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: d494ffa4d9f83b60fe66972ec2c0cf0301513b4a Maintainer: shein Status: ready -->
<!-- Reviewed: yes -->
<!-- $Revision$ -->
<sect1 xml:id="language.types.float" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Числа с плавающей точкой</title>
<para>
Числа с плавающей точкой или числа с плавающей запятой (также известные как "float", "double" или "real")
могут быть определены следующими синтаксисами:
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$a = 1.234;
$b = 1.2e3;
$c = 7E-10;
$d = 1_234.567; // начиная с PHP 7.4.0
?>
]]>
</programlisting>
</informalexample>
<para>
Формально, начиная с PHP 7.4.0 (ранее подчёркивание не разрешалось):
</para>
<informalexample>
<programlisting>
<![CDATA[
LNUM [0-9]+(_[0-9]+)*
DNUM ([0-9]*(_[0-9]+)*[\.]{LNUM}) | ({LNUM}[\.][0-9]*(_[0-9]+)*)
EXPONENT_DNUM (({LNUM} | {DNUM}) [eE][+-]? {LNUM})
]]>
</programlisting>
</informalexample>
<para>
Размер числа с плавающей точкой зависит от платформы, хотя максимум, как правило,
составляет 1.8e308 с точностью около 14 десятичных цифр (64-битный формат IEEE).
</para>
<warning xml:id="warn.float-precision">
<title>Точность чисел с плавающей точкой</title>
<para>
Числа с плавающей точкой имеют ограниченную точность. Хотя это
зависит от операционной системы, в PHP обычно используется формат
двойной точности IEEE 754, дающий максимальную относительную ошибку
округления порядка 1.11e-16.
Неэлементарные арифметические операции могут давать большие ошибки,
и, разумеется, необходимо принимать во внимание распространение ошибок
при совместном использовании нескольких операций.
</para>
<para>
Кроме того, рациональные числа, которые могут быть точно представлены
в виде чисел с плавающей точкой с основанием 10, например,
<literal>0.1</literal> или <literal>0.7</literal>, не имеют
точного внутреннего представления в качестве чисел с плавающей точкой
с основанием 2, вне зависимости от размера мантиссы.
Поэтому они и не могут быть преобразованы в их внутреннюю двоичную форму
без небольшой потери точности. Это может привести к неожиданным результатам:
например, <literal>floor((0.1+0.7)*10)</literal> скорее всего вернёт
<literal>7</literal> вместо ожидаемого <literal>8</literal>, так как
результат внутреннего представления будет чем-то вроде
<literal>7.9999999999999991118...</literal>.
</para>
<para>
Так что никогда не доверяйте точности чисел с плавающей точкой до последней цифры
и не проверяйте напрямую их равенство.
Если вам действительно необходима высокая точность, используйте
<link linkend="ref.bc">математические функции произвольной точности</link> и
<link linkend="ref.gmp">gmp</link>-функции.
</para>
<para>
"Простое" объяснение можно найти в <link xlink:href="&url.floating.point.guide;">руководстве
по числам с плавающей точкой</link>, которое также называется
"Why dont my numbers add up?" ("Почему мои числа не складываются?")
</para>
</warning>
<sect2 xml:id="language.types.float.casting">
<title>Преобразование в число с плавающей точкой</title>
<sect3 xml:id="language.types.float.casting.from-string">
<title>Из строк</title>
<simpara>
Если строка
<link linkend="language.types.numeric-strings">содержащая число</link>
или ведущая числовая, тогда она будет преобразована в соответствующее целочисленное значение,
в противном случае она преобразуется в ноль
(<literal>0</literal>).
</simpara>
</sect3>
<sect3 xml:id="language.types.float.casting.from-other">
<title>Из других типов</title>
<para>
Для значений других типов преобразование выполняется путём преобразования значения сначала в целое число (<type>int</type>), а затем в число с плавающей точкой (<type> float </type>).
Смотрите <link linkend="language.types.integer.casting">Преобразование в целое число</link> для получения
дополнительной информации.
</para>
<note>
<para>
Поскольку определённые типы имеют неопределённое поведение при преобразовании в
целое число (<type>int</type>), то же самое происходит и при преобразовании в
число с плавающей точкой (<type>float</type>).
</para>
</note>
</sect3>
</sect2>
<sect2 xml:id="language.types.float.comparison">
<title>Сравнение чисел с плавающей точкой</title>
<para>
Как указано выше, проверять числа с плавающей точкой на равенство
проблематично из-за их внутреннего представления.
Тем не менее, существуют способы для их сравнения, которые работают
несмотря на все эти ограничения.
</para>
<para>
Для сравнения чисел с плавающей точкой используется верхняя граница
относительной ошибки при округлении. Эта величина называется
машинной эпсилон или единицей округления (unit roundoff) и
представляет собой самую маленькую допустимую разницу при расчётах.
</para>
<informalexample>
<simpara>
<varname>$a</varname> и <varname>$b</varname> равны до 5-ти
знаков после точки.
</simpara>
<programlisting role="php">
<![CDATA[
<?php
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;
if (abs($a - $b) < $epsilon) {
echo "true";
}
?>
]]>
</programlisting>
</informalexample>
</sect2>
<sect2 xml:id="language.types.float.nan">
<title>NaN</title>
<para>
Некоторые числовые операции могут возвращать значение, представляемое
константой <constant>NAN</constant>. Данный результат означает неопределённое
или непредставимое значение в операциях с плавающей точкой. Любое строгое
или нестрогое сравнение данного значения с другим значением, кроме &true;, включая его
самого, возвратит &false;.
</para>
<para>
Так как <constant>NAN</constant> представляет собой неограниченное количество
различных значений, то <constant>NAN</constant> не следует сравнивать с
другими значениями, включая её саму. Вместо этого, для определения её наличия
необходимо использовать функцию <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
-->