-
Notifications
You must be signed in to change notification settings - Fork 73
/
float.xml
195 lines (171 loc) · 9.74 KB
/
float.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: a1e3d629b4f01ee41bd38391cd5c6ae5ee894cb3 Maintainer: shein Status: ready -->
<!-- Reviewed: no -->
<sect1 xml:id="language.types.float" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Числа с плавающей точкой</title>
<para>
Числа с плавающей запятой в руководстве называются «числами с плавающей точкой»,
поскольку в английском языке — языке оригинала PHP-руководства — целую и дробную часть в таких числах
разделяет точка, а не запятая. В других языках программирования числа с плавающей точкой называют также:
float, double или real. В PHP числа с плавающей точкой записывают следующими синтаксисами:
</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 ({LNUM}?"."{LNUM}) | ({LNUM}"."{LNUM}?)
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>
Кроме того, рациональные числа наподобие <literal>0.1</literal>
или <literal>0.7</literal>, которые легко точно представить
как числа с плавающей точкой по основанию 10 — в десятичной системе счисления,
внутренне невозможно точно представить как числа с плавающей точкой по основанию 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
-->