mirror of
https://github.com/php/doc-ru.git
synced 2025-08-16 18:22:04 +00:00
197 lines
9.2 KiB
XML
197 lines
9.2 KiB
XML
<?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 don’t 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
|
||
-->
|