В PHP всего восемь арифметических операторов. Наиболее распространенными являются сложение ( +
), вычитание ( -
), умножение ( *
) и деление ( /
). Несколько менее известный, хотя все еще очень важный оператор — по модулю ( %
). В этом уроке мы сосредоточимся на операторе по модулю. Мы обсудим, что он делает, и некоторые его практические применения.
Что делает оператор по модулю?
Если у вас есть две переменные $a
и $b
, то вычисление $a % $b
обычно произносится как «по модулю b» или «мод b» — даст вам остаток после деления $a
на $b
. Модуль по модулю является целочисленным оператором, поэтому он преобразует оба операнда в целые числа перед вычислением остатка. Таким образом, по модулю делается целочисленное деление, а затем возвращается то, что осталось от дивиденда.
Знак значения, возвращаемого операцией по модулю, определяется знаком дивиденда. При делении результатом после деления двух отрицательных чисел будет положительное число. Однако это не относится к оператору по модулю. Знак делителя не влияет на конечное значение.
Вот пара примеров:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<?php
echo 1089 % 37;
// Output: 16
echo 1089 % -37;
// Output: 16
echo -1089 % 37;
// Output: -16
echo -1089 % -37;
// Output: -16
echo -55.4 % -4.2;
// Output: -3
echo -55.9 % -4.8;
// Output: -3
echo -55 % -4;
// Output: -3
?>
|
С плавающей точкой по модулю
Если вы хотите вычислить остаток, когда два числа с плавающей точкой делятся друг на друга, вам придется использовать fmod($dividend, $divisor)
. Возвращает остаток с плавающей точкой после деления. Значение остатка будет иметь тот же знак, что и дивиденд, а его величина будет меньше делителя. Три числа связаны следующим образом:
1
|
$dividend = i*$divisor + $remainder
|
Здесь значение i
всегда будет целым числом.
Следует помнить, что арифметика с плавающей точкой не всегда точна из-за ограничений двоичного или десятичного представления дробей. Например, 1/3 не может быть точно представлена в десятичной форме. Вы можете продолжать писать 0.33333 …. но в какой-то момент вам придется остановиться. Вы будете приближаться к исходному значению с каждым дополнительным 3 в десятичном представлении, но значение все равно не будет точно 1/3.
Такая неточность вызывает проблемы с функцией fmod()
: результаты не совсем надежны.
Вот несколько примеров функции fmod()
:
1
2
3
4
5
6
7
8
9
|
<?php
echo fmod(18.8, 2);
// Output: 0.8
echo fmod(18.8, 0.2);
// Output: 0.2
?>
|
Второе значение не является точным, потому что 0,2 прекрасно делится на 18,8. Это всего лишь недостаток вычислений в формате с плавающей запятой, который используется компьютерами.
Использование оператора по модулю
В этом уроке мы ограничимся целым числом по модулю, потому что оно гораздо более распространено и имеет множество приложений.
Проверка, является ли число кратным некоторому другому числу
Результат оператора по модулю равен нулю, если первое число идеально делится на второе число. Это можно использовать для проверки, является ли одно число кратным другому в данной паре номеров. Вероятно, наиболее распространенным использованием этого свойства оператора по модулю является проверка, является ли число четным или нечетным. Вот пример:
01
02
03
04
05
06
07
08
09
10
11
12
|
<?php
$colors = [‘violet’, ‘indigo’, ‘blue’, ‘green’, ‘yellow’, ‘orange’, ‘red’];
$color_count = count($colors);
if($color_count % 2 == 0) {
echo ‘We have created some color pairs for you.’;
} else {
echo ‘Please specify one more or one less color to make pairing possible.’;
}
?>
|
В приведенном выше примере вы можете получить список цветов от пользователя и попросить его предоставить только четное количество цветов.
В приведенном ниже примере используются аналогичные рассуждения для создания групп по 5 человек в каждой. В реальной жизни вам придется использовать дополнительный код для группировки студентов, но основная идея проверки, является ли общее количество студентов кратным 5, не меняется.
01
02
03
04
05
06
07
08
09
10
11
|
<?php
$total_students = 25;
if($total_students % 5 == 0) {
echo ‘Each group of five students has been given an assignment.’;
} else {
echo ‘Sorry, it is impossible to create groups of five students right now.
}
?>
|
Изменение чисел, чтобы быть кратным некоторому другому числу
В приведенном выше разделе мы использовали оператор по модулю, чтобы информировать пользователей только о том, что вводить значения нужно только в определенных кратных числах. Если это невозможно, мы также можем заставить входное значение быть равным или кратным 5 или некоторому другому числу.
Оператор по модулю предоставляет целое число, оставшееся после деления первого числа на второе число. Это означает, что вычитание остатка из первого числа сделает его кратным второму числу. Например, 28 можно изменить на кратное 5, взяв по модулю 28% 5. В этом случае по модулю будет 3. Теперь мы можем вычесть 3 из исходного числа, чтобы сделать его кратным 5. Следующее line заставит любое положительное число x
быть кратным другому положительному числу y
, вычтя из него соответствующее значение.
1
|
x = x — (x % y)
|
В нашем предыдущем примере с 28 учениками мы могли просто оставить 3 учеников и сгруппировать других учеников вместе.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<?php
$total_students = 28;
if($total_students % 5 == 0) {
echo ‘Each group of five students has been given an assignment.’;
} else {
$removed_students = $total_students % 5;
$total_students -= $removed_students;
echo ‘We have created groups of five students by removing the last ‘.$removed_students.’
}
?>
|
Установить ограничение на вход
Как я упоминал в начале поста, в случае положительных чисел оператор по модулю вернет число от 0 до N — 1, где N — делитель. Это означает, что вы можете поставить заглушку на любой вход и выполнять некоторые операции многократно и последовательно. Вот пример:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
<?php
$colors = [‘violet’, ‘indigo’, ‘blue’, ‘green’, ‘yellow’];
$color_count = count($colors);
$total_images = 180;
$background_color = »;
for($i = 0; $i < $total_images; $i++) {
$background_color = $colors[$i % $color_count];
echo «Setting image background color to $background_color.»;
}
?>
|
В приведенном выше примере у нас всего пять цветов, но в общей сложности 180 изображений. Это означает, что нам придется постоянно повторять одни и те же пять цветов и назначать их всем нашим изображениям. Оператор по модулю идеально подходит для этой цели. Это ограничит значение $i % $color_count
от 0 до (5 — 1) или 4 включительно. Другими словами, мы сможем очень легко последовательно выбирать все цвета нашего массива.
Выполняйте какое-либо задание каждый раз в цикле
При обходе цикла мы можем проверять значение переменной, которое увеличивается с каждым проходом цикла, и выполнять определенную задачу после каждой n-й итерации. Один из примеров практического использования, который приходит на ум, — это информирование пользователей о длительном процессе. Допустим, вы вносите изменения в 1000 различных изображений с помощью PHP. Если изменения являются значительными, этот процесс займет некоторое время для обновления всех изображений.
В таких случаях у пользователей не будет возможности узнать, зависла ли программа или что-то действительно происходит. Что вы можете сделать, это сообщить о прогрессе пользователям после редактирования каждого 10-го изображения.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<?php
$total_images = 1000;
for($i = 1; $i <= $total_images; $i++) {
update_images($image_resource);
if($i % 10 == 0) {
$percent = $i*100/$total_images;
echo ‘Already processed ‘.$percent.’% images.’;
}
}
?>
|
Функция update_images()
в приведенном выше примере полностью составлена, но вы можете заменить ее другими процессами, такими как изменение размеров изображений, добавление водяных знаков, изменение их оттенков серого и т. Д. как программно редактировать изображения в PHP самостоятельно.)
Преобразование между различными единицами измерения
Оператор по модулю может также использоваться для преобразования между различными единицами измерения. Например, вы можете использовать его, чтобы изменить продолжительность, выраженную в секундах, на ту же продолжительность, выраженную в часах, минутах и секундах. Точно так же вы можете конвертировать большое количество сантиметров в километры, метры и сантиметры. Вот пример:
01
02
03
04
05
06
07
08
09
10
11
|
<?php
$total_seconds = 32987;
$hours = (int)($total_seconds / 3600);
$minutes = (int)(($total_seconds — 3600 * $hours )/60);
$seconds = $total_seconds % 60;
echo ‘Hours:’.$hours.’
?>
|
Мы начинаем с простого деления общего количества секунд на 3600 и преобразования значения в целое число. Это дает нам общее количество часов, поскольку каждый час имеет 3600 секунд.
На следующем шаге мы вычитаем 3600 * $hours
из исходного количества секунд. Это избавляет от всех секунд, которые мы конвертировали в часы. Теперь деление на 60 даст нам общее количество минут. Наконец, мы используем оператор по модулю, чтобы получить количество секунд.
Последние мысли
Как вы видели в этом руководстве, оператор modulo, хотя и прост в использовании, имеет множество приложений. Мы начали этот урок с рассмотрения по модулю положительных и отрицательных чисел, а также чисел с плавающей точкой. После этого мы рассмотрели некоторые распространенные сценарии, в которых мы будем использовать модуль.
Если у вас есть какие-либо вопросы, связанные с этим учебником, пожалуйста, дайте мне знать в комментариях. Есть ли у вас какие-либо другие применения по модулю? Пожалуйста, поделитесь ими с другими читателями, разместив их ниже.