Простая задача
Получить два целых числа — нижнюю и верхнюю границы диапазона. Вывести по одному в строке все целые числа, входящие в этот диапазон и кратные трем.
Пример работы программы
Ввод:
2 9
Вывод:
3
6
9
Решение 1. В лоб: -->
PHP:
function myfunc($a, $b)
{
do {
if ($a % 3 == 0) {
printf("%d\n", $a);
}
} while (($a = $a + 1) <= $b);
}
myfunc(2, 9);
Просто, быстро, на 2 и 9 работает без проблем. Но...Нам надо вывести каждое третье? НЕт смысла перебора всех подряд! Вдруг в диапазоне их будет миллиард, а не 8?
Решение 2. Математика, третий класс. Приводим начало диапазона к кратности трЁм и просто будем выводить каждое третье число.
PHP:
function myfunc1($a, $b)
{
if ( $a % 3 == 1 ) {
$a = $a + 2;
}
if ( $a % 3 == 2 ) {
$a = $a + 1;
}
do {
printf("%d\n", $a);
} while (($a = $a + 3) <= $b);
}
myfunc1(2, 9);
Решение 3. Краткость — сестра таланта. Заменим конструкцию $a = $a + ... на $a += ...
PHP:
function myfunc2($a, $b)
{
if ( $a % 3 == 1 ) {
$a+= 2;
}
if ( $a % 3 == 2 ) {
$a++;
}
do {
printf("%d\n", $a);
} while (($a+= 3) <= $b);
}
myfunc2(2, 9);
Неясно, что такое $a и $b. Когда программа будет развиваться, она рискует превратиться в набор совершенно никому не понятных идентификаторов.
Решение 4. Если сопоставить имена переменных с условием задачи, то $а — это начало диапазона, $b — его конец. Более уместны и понятны для них будут названия $min и $max.
PHP:
function myfunc3($min, $max)
{
if ( $min % 3 == 1 ) {
$min+= 2;
}
if ( $min % 3 == 2 ) {
$min++;
}
do {
printf("%d\n", $min);
} while (($min+= 3) <= $max);
}
myfunc3(2, 9);
Зачем всегда дважды вычислять остаток и проверять $min на кратность?
Решение 5. Во-первых, вычислим остаток один раз и запомним его в переменнойс логичным названием $remainder (англ. остаток). Во-вторых, добавим ключевое слово else между условиями, так как остаток не может оказаться двойкой, если он уже оказался единицей.
PHP:
function myfunc4($min, $max)
{
$remainder = $min % 3;
if ( $remainder == 1 ) {
$min+= 2;
}
if ( $remainder == 2 ) {
$min++;
}
do {
printf("%d\n", $min);
} while (($min+= 3) <= $max);
}
myfunc4(2, 9);
Значение переменной $min (нижней границы диапазона) стремится вверх, теряя соответствие своего названия. Под конец работы программы в ней уже будет явно не минимум.
Решение 6.
Лучше всего характер этого меняющегося значения, кратного тройке, определяет слово «кратное». По-английски — $$multiple. И здесь всё же лучше использовать цикл for.
PHP:
function myfunc5($min, $max)
{
$multiple = $min;
$remainder = $min % 3;
if ( $remainder == 1 ) {
$multiple += 2;
} else if ( $remainder == 2 ) {
$multiple += 1;
}
for ( ; $multiple <= $max; $multiple += 3 ) {
printf("%d\n", $multiple);
}
}
myfunc5(2, 9);
Если для поиска кратного тройке числа программисту потребовалось дважды произвести проверку, то сколько же их будет, когда нужно будет найти число, кратное сорока двум? Сорок одна? А кратное миллиарду?
Решение 7. Расширяем горизонты. Применим более продвинутые познания арифметики. Если из числа вычесть остаток от его деления на три, то результат будет делиться на три! Важно только соблюдать условие задачи и убедиться, что результат не меньше минимума.
PHP:
function myfunc6($min, $max) {
$multiple = $min - $min % 3;
if ($multiple < $min) {
$multiple += 3;
}
for (; $multiple <= $max; $multiple += 3) {
printf("%d\n", $multiple);
}
}
myfunc6(2, 9);
В коде присутствуют «магические» числа. Что обозначает тройка? И что будет, если вместо кратности тройке нужно будет вывести числа, кратные пяти? Нужно вносить правки в несколько мест? Больше правок — выше вероятность ошибок.
Решение 8. Разоблачение магии. Введем третий параметр под названием divisor (англ. делитель). И назовем функцию правильно.
PHP:
function getMultiples($min, $max, $divisor) {
$multiple = $min - $min % $divisor;
if ( $multiple < $min ) {
$multiple += $divisor;
}
for ( ; $multiple <= $max; $multiple += $divisor ) {
printf("%d\n", $multiple);
}
}
getMultiples(2,9, 3);
На данной прекрасной ноте мы завершим работу над этой простой задачей, которая теперь позволяет эффективно находить кратные числа и легко менять делитель.
Выводы:
В реальной жизни задачи будут объемнее и сложнее, а различные ошибки, невнимательность и недоработки в коде могут в итоге приводить к гораздо более серьезным и иногда даже очень печальным последствиям.
Cтатьи, документация, поисковые системы и прочие инструменты самообучения — это великолепно и мы призываем вас активно ими пользоваться. У них множество плюсов и зачастую только один общий минус — они не дадут обратную связь и комментарии к вашим решениям.
PS. Мы намеренно «упустили», что решения 2–6 некорректно работают с отрицательными числами, так как остаток может оказаться −1 или −2. Кто самостоятельно заметил — молодец.
PPS. Хотите улучшить свои шансы писать нормальный код? Наверное, вы уже догадываетесь, куда следует пойти.
© 2018 Codeby School PHP Club