Часто при создании интернет магазинов и в других местах, где нужно показать количество во множественном числе - нужно пойти на некоторые хитрости. Первое решение, самое простое, вывести слово перед числом и указать некую общую форму, например, Товаров в корзине: 3
, или в скобках прописать 3 товара(ов)
, но мы то хотим сделать всё красиво, поэтому, разберемся в сути вопроса. Нам нужно понять как подставлять правильное окончание слов в зависимости от количества.
Статья несет больше образовательный характер, чтобы получить готовый алгоритм и не вдаваться в подробности - можете пролистать до конца. Если загуглить склонение существительных после поличества, то можно найти много готовых примеров кода на разных языках программирования - JavaScript, C, PHP, но если вникнуть в суть самого алгоритма, то вы его сможете написать на любом языке, хоть на паскале, поэтому, решил разобраться в этой теме...
Для начала попробуем просклонять несколько слов - Товар, Ящик, Зубочистка, Конфета
Количество\Слово | Товар | Ящик | Зубочистка | Конфета |
---|---|---|---|---|
0 | Товаров | Ящиков | Зубочисток | Конфет |
1 | Товар | Ящик | Зубочистка | Конфета |
2 | Товара | Ящика | Зубочистки | Конфеты |
3 | Товара | Ящика | Зубочистки | Конфеты |
4 | Товара | Ящика | Зубочистки | Конфеты |
5 | Товаров | Ящиков | Зубочисток | Конфет |
6 | Товаров | Ящиков | Зубочисток | Конфет |
7 | Товаров | Ящиков | Зубочисток | Конфет |
8 | Товаров | Ящиков | Зубочисток | Конфет |
9 | Товаров | Ящиков | Зубочисток | Конфет |
10 | Товаров | Ящиков | Зубочисток | Конфет |
Попробуем упростить эту таблицу
Количество\Слово | Товар | Ящик | Зубочистка | Конфета |
---|---|---|---|---|
0, 5-10 | Товаров | Ящиков | Зубочисток | Конфет |
1 | Товар | Ящик | Зубочистка | Конфета |
2-4 | Товара | Ящика | Зубочистки | Конфеты |
Т.е. мы имеем всего три формы слова, если в пределах от 0 до 9
- Для одного - именительный падеж (кто/что)
- От 2х до 4х - родительный падеж (кого/чего)
- От 5 до 9 и 0 - множественное число (много конфет, много ящиков, много товаров...)
но количество 0 нужно обратывать правильно, писать пусто или нет в корзине ничего или конфет сегодня не будет...
Продолжим наше исследование на диапазоне от 11 до 30, теперь уже по одному слову...
Число | Форма |
---|---|
11 | Товаров |
12 | Товаров |
13 | Товаров |
14 | Товаров |
15 | Товаров |
16 | Товаров |
17 | Товаров |
18 | Товаров |
19 | Товаров |
20 | Товаров |
21 | Товар |
22 | Товара |
23 | Товара |
24 | Товара |
25 | Товаров |
26 | Товаров |
27 | Товаров |
28 | Товаров |
29 | Товаров |
30 | Товаров |
С 11 до 19 ситуация не меняется, но вот если сравнить таблицу первую с 0 до 10 с таблицей от 20 до 30, то ситуация в точности повторяется, очень интересно!
А что за числа с 11 до 19, это числа с окончанием "надцать" (одинадцать, пятнадцать, девятнадцать).
Теперь можете перепроверить, но я уже проверил сам, с 0 до 100 ситуация повторяет в точности ситуацию с 0 до 10, исключением из этого будет только то, что заканчивается на "надцать". Я бы даже сказал что от 0 до 9, во всех числах берется последняя цифра и по ней решается какая форма слова будет.
А что дальше? Дальше подставляйте хоть 1000, хоть миллион, ситуация повторится, решающими будут две последние цифры, если число заканчивается на 11-19 и во всех остальных случаях одна последняя цифра.
Какой алгоритм получится в результате?
- Отсекаем две последние цифры от числа, проверяем не находится ли это в диапазоне от 11 до 19, если так, то отдаем множественное число (п3).
- Отсекаем еще раз от этого одну последнюю цифру - если 1, то отдаем именительный падеж (п1)
- Если это цифра от 2 до 4, то отдаем родительный падеж.
- Во всех остальных случаях множественное число.
В некоторых алгоритмах просят вводить три формы слова, где-то 1,3,5, а где-то 1,2,4 или 1,2,7, но это сути не меняет, мы будем входными параметрами в функции использовать количество 1 (яблоко),2 (яблока),5 (яблок).
Пример на моем любимом PHP
$n - количество
$f1 = яблоко
$f2 = яблока
$f5 = яблок
public static function num_morph($n, $f1, $f2, $f5)
{
$n = (abs($n) % 100); //отсекаем две последние цифры от цисла
//если это от 11 до 19, вернем множ. число
if ($n>=11 && $n<=19) return $f5;
$n1= $n % 10; //отсекаем от этого последнюю цифру
//единственное число
if ($n1==1) return $f1;
//родительный падеж
if ($n1>1 && $n1<5) return $f2;
//во всех остальных случаях множественное число
return $f5;
}
Если остались вопросы - задавайте в комментариях...