base12 13

Обработка чисел и математические операции

Программисты, которым требуется осуществлять ответственные числовые, научные или статистические вычисления, вряд ли станут рассматривать язык составления сценариев для веб в качестве приемлемого кандидата на эту роль. Но, несмотря на сказанное, язык PHP предлагает великолепный набор функций, которые полностью обеспечивают решение большинства математических задач, возникающих в процессе выполнения сценариев для веб. Кроме того, язык PHP предоставляет некоторые более расширенные возможности, такие как арифметика чисел произвольной точности, а также средства библиотек хэширования и криптографических библиотек.

Разработчики языка PHP приняли вполне обоснованный подход и не стали предпринимать какие-либо попытки снова изобретать колеса, предназначенные для указанной цели. Дело в том, что многие из наиболее фундаментальных математических функций, применяемых в языке PHP, являются просто оболочками вокруг аналогов этих функций на языке C.

Математические операции

Большинство математических действий в языке PHP осуществляется в форме встроенных функций, а не в форме операций. Кроме операций сравнения, язык PHP предлагает пять операций выполнения простых арифметических действий, а также некоторые сокращенные операции, позволяющие составлять более краткие выражения инкремента и декремента, а также присваивания.

Арифметические операции

К пяти основным арифметическим операциям относятся те операции, которые обычно реализованы в любом четырехфункциональном калькуляторе, а также операция деления по модулю (%). Краткое описание арифметических операций приведено в таблице:

Арифметические операции
Операция Описание
+ Возвращает сумму значений двух своих операндов
- Если имеются два операнда, то значение правого операнда вычитается из значения левого. Если имеется только правый операнд, то операция возвращает значение этого операнда с обратным знаком
* Возвращает произведение значений двух своих операндов
/ Возвращает результат деления с плавающей точкой значения левого операнда на значение правого операнда
% Возвращает остаток от целочисленного деления значения левого операнда на абсолютное значение правого операнда

При использовании в программе первых трех описанных выше арифметических операций (+,-,*) следует учитывать, что при выполнении этих операций происходит распространение типа от значений с плавающей точкой двойной точности к целочисленным значениям. Под этим подразумевается следующее: если оба операнда операции являются целыми числами, то результатом становится целое число, а если хотя бы один из операндов представляет собой число с плавающей точкой двойной точности, то результатом становится число с плавающей точкой двойной точности. Такого же рода распространение типа происходит и при выполнении операции деления; кроме того, возникает такой дополнительный эффект, что результат становится числом с плавающей точкой двойной точности, если деление не осуществляется без остатка (нацело).

Операция деления по модулю (%) в языке PHP принимает целочисленные операнды, а если эта операция применяется к числам с плавающей точкой двойной точности, то эти числа предварительно преобразуются в целые числа (путем отбрасывания дробной части). Результатом такой операции всегда является целое число.

Операции инкремента и декремента

Значительная часть синтаксиса языка PHP унаследована от языка C, а программисты C славятся любовью к краткости и гордятся этим. Операции инкремента и декремента, взятые из языка C, позволяют более кратко представлять выражения типа $count = $count + 1, которые обычно встречаются в программах достаточно часто.

Операция инкремента (++) применяется для добавления единицы к значению той переменной, на которую распространяется эта операция, а операция декремента (--) вычитает единицу из значения такой переменной.

Каждая из этих двух операций имеет две разновидности — суффиксную (в этой форме знак операции помещается непосредственно вслед за переменной, на которую распространяется операция) и префиксную (в этой форме знак операции помещается непосредственно перед переменной, на которую распространяется операция). Обе разновидности имеют один и тот же побочный эффект, связанный с изменением значения переменной, но суффиксные и префиксные операции возвращают разные значения при использовании в качестве выражений. Суффиксная операция действует так, что значение переменной изменяется после возврата значения выражения, а префиксная операция действует таким образом, что вначале изменяется значение, а затем переменной возвращается новое значение. Указанное различие можно обнаружить, используя операции декремента и инкремента в операторах присваивания:

Код PHP
$count = 0;
$result = $count++;
echo 'Результат инкремента $count++: '.$result.'<br>';

$count = 0;
$result = ++$count;
echo 'Результат инкремента ++$count: '.$result.'<br>';

Приведенные операторы формируют следующий вывод в окне браузера:

Операции инкремента

В этом примере оператор $result = $count++ полностью эквивалентен операторам:

Код PHP
$result = $count;
$count = $count + 1;

Наряду с этим оператор $result = ++$count эквивалентен таким операторам:

Код PHP
$count = $count +1;
$result = $count;

Операции присваивания

Операции инкремента (и декремента) позволяют уменьшить объем кода, необходимого для добавления единицы к значению переменной, но не позволяют сократить объем кода, в котором переменной присваивается результат сложения ее значения с другим числом или результат выполнения других арифметических действий. К счастью, все пять арифметических операций имеют соответствующие им операции присваивания (+=, -=, *=, /= и %=), позволяющие присвоить переменной в одном кратком выражении результат выполнения арифметической операции над значением этой переменной. Например, оператор

Код PHP
$count = $count * 3;

может быть сокращенно представлен таким

Код PHP
$count *= 3;

Простые математические функции

Следующий этап усложнения программы по сравнению с той, в которой применяются только арифметические операции, состоит в использовании всевозможных функций. Функции позволяют выполнять такие задачи, как преобразование из одного числового типа в другой (см. статью "Типы данных") и поиск минимального или максимального числа во множестве чисел. В следующей таблице представлены простые математические функции:

Простые математические функции PHP
Функция Описание
floor() Принимает единственный фактический параметр (как правило, число с плавающей точкой двойной точности) и возвращает наибольшее целое число, которое меньше или равно этому фактическому параметру (округление в меньшую сторону)
ceil() Имя этой функции представляет собой сокращение от слова ceiling (потолок). Функция принимает единственный фактический параметр (как правило, число с плавающей точкой двойной точности) и возвращает наименьшее целое число, которое больше или равно этому фактическому параметру (округление в большую сторону)
round() Принимает единственный фактический параметр (как правило, число с плавающей точкой двойной точности) и возвращает ближайшее целое число
abs() Модуль числа. Если единственный числовой фактический параметр имеет отрицательное значение, то функция возвращает соответствующее положительное число; если фактический параметр является положительным, то функция возвращает сам фактический параметр
min() Принимает любое количество числовых фактических параметров (но не менее одного) и возвращает наименьшее из всех значений фактических параметров
max() Принимает любое количество числовых фактических параметров (но не менее одного) и возвращает наибольшее из всех значений фактических параметров

Например, результат следующего выражения равен 3, поскольку значение каждого выражения с вызовом функции также равно 3:

Код PHP
$result = min(3, abs(-3), max(round(2.7), ceil(2.3), floor(3.9)));

Выработка случайных чисел

В языке PHP применяются два генератора случайных чисел (вызываемых соответственно с помощью функций rand() и mt_rand()). С каждым из этих генераторов связаны по три функции одинакового назначения: функция задания начального значения (srand() и mt_srand()), сама функция получения случайного числа и функция, осуществляющая выборку наибольшего целого числа, которое может быть возвращено генератором ((getrandmax() и mt_getrandmax())). Функции getrandmax() и mt_getrandmax() возвращают значение наибольшего числа, которое может быть возвращено функцией rand() или mt_rand(), на платформах Windows это значение ограничено величиной 32768.

Выбор конкретной функции выработки псевдослучайных чисел, которая используется в функции rand(), может зависеть от того, с какими именно библиотеками был откомпилирован интерпретатор PHP. В отличие от этого в генераторе mt_rand() всегда используется одна и та же функция выработки псевдослучайных чисел (mt — сокращение от Mersenne Twister), причем автор оперативной документации к функции mt_rand() утверждает, что эта функция к тому же является более быстродействующей и "более случайной" (с точки зрения криптографии), чем rand(). У нас нет оснований сомневаться в истинности этих утверждений, поэтому мы предпочитаем использовать функцию mt_rand(), а не rand().

При использовании некоторых версий PHP для некоторых платформ создается впечатление, что функции rand() и mt_rand() вырабатывают на первый взгляд вполне приемлемые случайные числа, даже без предварительного задания начального значения. Но такому впечатлению не следует доверять. Во-первых, программы, в которых используются функции выработки случайных чисел без задания начального значения, невозможно легко переносить на другие платформы, а, во-вторых, надежная работа указанных функций без задания начального значения не гарантируется.

Типичный способ задания начального значения для любого из генераторов случайных чисел PHP (с использованием функции mt_srand() или srand()) заключается в следующем:

Код PHP
mt_srand((double)microtime()*1000000);

В этом операторе задается начальное значение генератора, равное количеству микросекунд, истекших к данному времени с момента отсчета последней целой секунды. (Приведение типа к типу double в этом операторе действительно необходимо, поскольку функция microtime() возвращает строку, которая рассматривается как целое число в операции умножения, но не в операции передачи параметров в функцию.) Рекомендуем читателю вводить указанный оператор задания начального значения, даже если ему не совсем понятно назначние этого оператора; достаточно просто поместить данный оператор на каждую страницу PHP, всего лишь один раз, перед использованием соответствующей функции mt_rand() или rand(), и этот оператор будет гарантировать, что отправная точка изменится и поэтому каждый раз будут вырабатываться различные случайные последовательности.

Данный конкретный метод задания начального значения был глубоко продуман теми специалистами, которые полностью понимают все нюансы выработки псевдослучайных чисел, поэтому, скорее всего, навсегда останется лучшим по сравнению с любыми попытками какого-то отдельного программиста придумать что-то более "заковыристое".

Очевидно, что указанные функции выработки псевдослучайных чисел возвращают только целые числа, но случайное целое число из заданного диапазона можно легко преобразовать в соответствующее число с плавающей точкой (скажем, в число из диапазона от 0.0 до 1.0 включительно) с помощью выражения наподобие rand() / getrandmax(). После этого указанный диапазон можно масштабировать и сдвигать по мере необходимости. Ниже показан пример:

Код PHP
// Допустим нам нужно сгенерировать случайное число от 100.0 до 120.0
$random = 100.0 + 20.0 * mt_rand() / mt_getrandmax();
echo $random.'<br>';

// Выработка целых чисел (100 - 120);
echo round($random);

Попробуйте обновить страницу с этим кодом несколько раз, чтобы убедиться в генерации случайных чисел.

Математические константы

В PHP версии 4.0 существовала только одна математическая константа, описанная в документации — M_PI (значение числа π, представленное в виде числа с плавающей точкой двойной точности). А начиная с версии PHP 4.0.2 было введено много новых констант. Большинство этих новых констант относились к числу π (или к кратным ему значениям), числу e (или к кратным ему значениям), а также к квадратным корням; кроме того, некоторые константы относились к другим типам. Но в следующих выпусках по ряду причин список констант снова сократился до сравнительно небольшого количества заранее заданных математических констант:

Математические константы PHP
Константа Описание
M_PI π
M_PI_2 π / 2
M_PI_4 π / 4
M_1_PI 1 / π
M_2_PI 2 / π
M_2_SQRTPI 2 / sqrt(π)
M_E e
M_SQRT2 sqrt(2)
M_SQRT1_2 1 / sqrt(2)
M_LOG2E log2(e)
M_LOG10E lg(e)
M_LN2 loge(2)
M_LN10 loge(10)

Проверка формата чисел

В языке PHP предусмотрен ряд функций, позволяющих выполнять проверку правильности представления чисел. Несмотря на то что в языке PHP отсутствует строгий контроль типов, рекомендуется в случае необходимости применять некоторые из этих проверок в коде, чтобы иметь возможность прогнозировать характеристики полученных результатов, а также выбирать наилучший способ их обработки.

Первая и наиболее простая проверка заключается в использовании функции is_numeric(). Как и при осуществлении большинства других таких проверок, функция is_numeric возвращает булев результат - true, если переданный ей параметр представляет собой числовые данные любого типа (со знаком или без знака, целочисленные или с плавающей точкой) либо математическое выражение, которое возвращает допустимое числовое значение.

С помощью функций is_int() и is_float можно определить является ли число целым или дробным. Еще две проверки являются немного более сложными: функции is_finite() и is_infinite() позволяют выполнить именно те проверки, на которые указывают их имена (является ли число конечным или бесконечным). Но, строго говоря, диапазон значений, на которые распространяются эти функции, не может включать актуальной бесконечности (и может ли вообще быть проверено, имеет ли числю бесконечно большое значение?). Вместо этого используются пределы диапазона значений с плавающей точкой, допустимые в конкретной системе.

Ниже показан пример использования этих функций:

Код PHP
is_numeric(4);				// true
is_numeric(25 - 6);			// true
is_numeric("25");			// true
is_numeric("25 - 6");		// false

is_int(4);					// true
is_int(4.2);				// false
is_int("4");				// false - данная проверка строже, чем проверка с помощью функции is_numeric()

is_float(4);				// false
is_float(4.0);				// true
is_float(M_PI);				// true

Преобразование систем счисления

По умолчанию в языке PHP для прямого и обратного преобразования числовых значений из внешнего представления во внутреннее применяется основание системы счисления 10. Кроме того, можно сообщить интерпретатору PHP, что во внешнем представлении используются восьмеричные числа, заданные по основанию 8 (для этого перед числом необходимо ввести ведущий 0), или шестнадцатеричные числа, заданные по основанию 16 (для этого перед числом необходимо ввести префикс 0x).

Безусловно, после преобразования чисел из внешнего представления во внутреннее они хранятся в памяти в двоичном формате, а все основные арифметические и математические вычисления осуществляются в самой операционной системе по основанию 2. Кроме того, в языке PHP предусмотрен ряд функций для преобразования чисел из одного основания системы счисления в другое. Общие сведения об этих функциях приведены в таблице ниже:

Функции преобразования систем счисления
Функция Описание
BinDec() Принимает единственный строковый параметр, представляющий собой двоичное целое число (число по основанию 2), и возвращает строковое представление этого числа по основанию системы счисления 10
DecBin() Аналогична BinDec(), но преобразует из основания системы счисления 10 в основание системы счисления 2
OctDec() Аналогична BinDec(), но преобразует из основания системы счисления 8 в основание системы счисления 10
DecOct() Аналогична BinDec(), но преобразует из основания системы счисления 10 в основание системы счисления 8
HexDec() Аналогична BinDec(), но преобразует из основания системы счисления 16 в основание системы счисления 10
DecHex() Аналогична BinDec(), но преобразует из основания системы счисления 10 в основание системы счисления 16
base_convert() Принимает строковый параметр (представляющий целое число, которое подлежит преобразованию) и два целочисленных параметра (исходное и желаемое основание). Возвращает строку, представляющую преобразованное число. В этой строке цифры старше, чем 9 (от 10 до 35), представлены символами a-z. И исходное, и желаемые основания должны находиться в пределах 2-36

Все функции преобразования систем счисления являются функциями специального назначения, преобразующими числа из одного конкретного основания в другое. Исключением является функция base_convert(), которая принимает произвольные параметры с обозначением начального и результирующего основания.

Обратите внимание на то, что все функции преобразования систем счисления принимают строковые параметры и возвращают строковые значения, но можно использовать десятичные числовые параметры и полагаться на правильное выполнение преобразования типа интерпретатором PHP. Иными словами, варианты вызова DecBin("1234") и DecBin(1234) приводят к получению одинакового результата.

Экспоненты и логарифмы

Язык PHP включает стандартные экспоненциальные и логарифмические функции двух разноввдностей — для работы по основанию 10 и основанию е (которые приведены в таблице).

Экспоненциальные функции
Функция Описание
pow() Принимает два числовых параметра и возвращает первый параметр, возведенный в степень, равную второму параметру. Значение выражения pow($х, $у) равно xy
exp() Принимает единственный параметр и возводит число e в степень, равную этому показателю степени. Значение выражения exp($х) равно ex
log() Функция натурального логарифма (ln). Принимает единственный параметр и возвращает его логарифм по основанию e
log10() Принимает единственный параметр и возвращает его десятичный логарифм (lg)

В языке PHP предусмотрена функция exp() для возведения числа e в указанную степень, но отсутствует функция с одним параметром, с помощью которой можно было бы возвести в указанную степень число 10. Однако вместо этой функции можно использовать функцию pow() с двумя параметрами, задавая 10 в качестве первого параметра.

Можно убедиться в том, что экспоненциальные и логарифмические функции с одним и тем же основанием являются обратными по отношению друг к другу, проведя проверку идентичности полученных результатов таким образом:

Код PHP
$test_449 = 449.0;
$test_449 = pow(10, exp(log(log10($test_449)))); 

echo "test_449 = $test_449";     // test_449 = 449

Тригонометрические функции

В языке PHP предусмотрен стандартный набор основных тригонометрических функций, общие сведения о которых приведены в таблице:

Тригонометрические функции
Функция Описание
pi() Не принимает параметров и возвращает приближенное значение числа π (3.1415926535898). Может использоваться как взаимозаменяемая с константой M_PI
sin() Принимает числовой параметр в радианах и возвращает синус параметра в виде числа с плавающей точкой двойной точности
cos() Принимает числовой параметр в радианах и возвращает косинус параметра в виде числа с плавающей точкой двойной точности
tan() Принимает числовой параметр в радианах и возвращает тангенс параметра в виде числа с плавающей точкой двойной точности
asin() Принимает числовой параметр и возвращает арксинус параметра в радианах. Входные данные должны находиться в пределах от -1 до 1 (получение функцией входных данных, выходящих за пределы этого диапазона, приводит к получению результата NAN). Результаты находятся в диапазоне от -π/2 до π/2
acos() Принимает числовой параметр и возвращает арккосинус параметра в радианах. Входные данные должны находиться в пределах от -1 до 1 (получение функцией входных данных, выходящих за пределы этого диапазона, приводит к получению результата NAN. Результаты находятся в диапазоне от 0 до π
atan() Принимает числовой параметр и возвращает арктангенс параметра в радианах. Результаты находятся в диапазоне от -π/2 до π/2

Ниже показан пример составления таблицы вычисления тригонометрических функций для "стандартных" углов:

Код PHP
function display_trigonometry($func_array, $input_array)
{
	// Заголовок функции
	echo '<table border="1"><tr><th>Значение/функция</th>';
	foreach($func_array as $func)
	{
		echo "<th>$func</th>";
	}
	echo '</tr><tr>';
	
	// Вывести остальную часть таблицы
	foreach($input_array as $input)
	{
		echo '<th>'.sprintf("%.4f",$input).'</th>';
		foreach($func_array as $func)
		{
			echo '<td>';
			printf("%4.4f", $func($input));
			echo '</td>';
		}
		echo '</tr><tr>';
	}
	
	echo '</tr></table>';
}

display_trigonometry(array('sin', 'cos', 'tan'), 
	array(0, M_PI / 6, M_PI / 3, M_PI / 2, M_PI));
Пример использования тригонометрических функций в PHP

Получение очень больших (но не бесконечных) значений тангенса обусловлено тем, что теоретически знаменатели должны быть равными нулю, но в действительности немного отличаются от нуля из-за ошибок округления.

Вычисление с произвольной точностью (с использованием функций BC)

Целочисленные типы и типы с плавающей точкой двойной точности полностью подходят для решения большинства математических задач, возникающих при выполнении сценариев для веб, но для хранения каждого экземпляра значения, представленного с помощью этих типов, предусмотрен фиксированный объем компьютерной памяти, поэтому на размеры и точность представления чисел этих типов неизбежно налагаются ограничения.

Безусловно, точные диапазоны значений данных этих типов могут зависеть от архитектуры серверного компьютера, но значения целых чисел обычно могут находиться в пределах от -231-1 до 231-1, а числа с плавающей точкой двойной точности могут представлять числа с точностью примерно от 13 до 14 десятичных цифр. С другой стороны, для решения задач, требующих использования более широкого диапазона представления или большей точности, в языке PHP предусмотрены математические функции с произвольной точностью (называемые также функциями BC — по имени вычислительной утилиты с произвольной точностью, основанной на средствах системы Unix).

Может оказаться, что функции с произвольной точностью не включены в компиляцию интерпретатора PHP, особенно если пользователь проводил такую компиляцию самостоятельно, поскольку для этого пользователь должен был знать, что на этапе настройки конфигурации необходимо включить в состав параметров флажок --enable-bcmath. Чтобы проверить, имеется ли доступ к указанным функциям, попытайтесь вычислить выражение bcadd("1","1"). Если будет получено сообщение об ошибке, в котором говорится о неопределенной функции, то вам потребуется снова настроить конфигурацию и перекомпилировать интерпретатор PHP.

В функциях BC в качестве параметров и возвращаемых значений используются не числовые типы с представлением фиксированной длины, а строки. Поскольку в языке PHP длина строк ограничивается только объемом доступной памяти, числа, используемые в расчетах, могут иметь любую длину. Основополагающие вычисления осуществляются в десятичном виде и во многом напоминают те, которые может выполнить и человек с помощью карандаша и бумаги (если сможет действовать очень быстро и запасется терпением). Функции BC, оперирующие целыми числами, действуют точно и позволяют использовать столько цифр, сколько потребуется, а в функциях, оперирующих числами с плавающей точкой, вычисления выполняются с точностью до заданного количества десятичных разрядов. Общие сведения о функциях BC приведены в таблице ниже:

Математические функции с произвольной точностью (функции BC)
Функция Описание
bcadd() Принимает два строковых параметра, представляющих числа, и необязательный целочисленный параметр с обозначением масштабного множителя. Возвращает сумму первых двух параметров в виде строки, с количеством десятичных позиций в результате, определяемом параметром с обозначением масштабного множителя. Если параметр с обозначением масштабного множителя не задан, то используется заданный по умолчанию масштабный множитель
bcsub() Аналогична bcadd(), за исключением того, что возвращает результат вычитания второго параметра от первого
bcmui() Аналогична bcadd(), за исключением того, что возвращает результат умножения своих параметров
bcdiv() Аналогична bcadd(), за исключением того, что возвращает результат деления первого параметра на второй
bcmod() Возвращает модуль (остаток) от деления первого параметра на второй. Поскольку возвращаемое значение относится к целочисленному типу, функция не принимает параметр с обозначением масштабного множителя
bcpow() Возводит первый параметр в степень, указанную вторым параметром. Количество десятичных позиций в результате определяется масштабным множителем, если он задан
bcsqrt() Возвращает квадратный корень параметра с количеством десятичных позиций, которое определяется значением необязательного масштабного множителя
bcscale() Устанавливает заданный по умолчанию масштабный множитель для последующих вызовов функции BC

Большинство из этих функций принимают в качестве последнего параметра необязательный масштабный множитель (целое число), который определяет, какое количество десятичных позиции должно быть в результате. Если такой параметр не задан, то в качестве масштабного множителя используется заданный по умолчанию масштабный множитель, который, в свою очередь, может быть установлен путем вызова функции bcscale(). Заданная по умолчанию величина для этого заданного по умолчанию значения (т.е. величина, которая используется, если в сценарии не применяется вызов функции bcscale()) может быть также задана в файле инициализации php.ini.

Ниже приведен пример использования функции с произвольной точностью для точного выполнения целочисленных арифметических операций. Выполнение следующего кода:

Код PHP
for ($x = 1; $x < 25; $x++) 
{
	echo "$x<sup>$x</sup> = ".bcpow($x, $x).'<br>';
}
Точное вычисление астрономических величин с помощью функций BC

Если бы для этих вычислений использовался обычный целочисленный тип PHP, то переполнение целого числа произошло бы задолго до конца вычисления, поэтому в остальной части цикла расчеты выполнялись бы в целях получения приближенного числа с плавающей точкой.

Массивы
Обработка форм

Комментарии (0)

Результаты поиска по запросу

Система Orphus