Здравствуйте! Недавно столкнулся с задачей склонения существительных после числовых значений, например 1 удав, но 2 удава. Прежде чем лезть в просторы интернета за готовыми вариантами решений, мне захотелось самому понять принцип склонения существительных.
Итак для начала я решил составить таблицу возможных окончаний слова в зависимости от числительного. Поскольку выше были упомянуты удавы, то на них и остановимся.
0 | -ов | 10 | -ов | 20 | -ов |
1 | — | 11 | -ов | 21 | — |
2 | -а | 12 | -ов | 22 | -а |
3 | -а | 13 | -ов | 23 | -а |
4 | -а | 14 | -ов | 24 | -а |
5 | -ов | 15 | -ов | 25 | -ов |
6 | -ов | 16 | -ов | 26 | -ов |
7 | -ов | 17 | -ов | 27 | -ов |
8 | -ов | 18 | -ов | 28 | -ов |
9 | -ов | 19 | -ов | 29 | -ов |
Из данной таблицы можно понять, что:
- Вариантов возможных окончаний три.
- Окончания повторяются циклично в зависимости от последней цифры числа.
- Числа 11-14 выбиваются из общего принципа склонения существительных
Следовательно получается, если взять последние две цифры числительного и получившееся число находится в диапазоне 11-14 включительно, то окончание должно быть «-ов», во всех остальных случаях для определения окончания будет достаточно одной последней цифры числа.
окончание «-ов», если последняя цифра 0 (ноль) либо 5-9
окончание «-«, если последняя цифра 1
окончание «-а», если окончание 2-4
Теперь общий принцип вычисления окончания думаю стал понятен, можно приступить к программированию. Наиболее интересным и лаконичным решением мне показался следующий код, найденный на сайте expange.ru и слегка преобразованный.
public static function numberEnd($number, $value, $suffix) { //ключи массива suffix $keys = array(2, 0, 1, 1, 1, 2); //берем 2 последние цифры $mod = $number % 100; //определяем ключ окончания $suffix_key = $mod > 4 && $mod < 21 ? 2 : $keys[min($mod%10, 5)]; return $value . $suffix[$suffix_key]; }
Суть данного кода в следующем.
$sufix массив возможных окончаний, выставленных в порядке соответствия числительным 1, 2, 5.
$keys содержит ключи массива окончаний соответствующие числительным 0-5.
Как мы уже выяснили выше, для того чтобы узнать окончание по последней цифре, нужно выяснить не заканчивается ли число на 11-14. Но поскольку мы берем 2 цифры и из таблицы видно, что диапазон окончаний у числительных 11-14 попадает в более обширный диапазон 5-20, поэтому во время проверки возьмем его.
Если число не попадает под наш диапазон, то берем от него последнюю цифру и проверяем так, если бы это было число в диапазоне 0-9.
min($mod%10, 5) Поскольку окончания после числительного 5 идут одинаковые (в пределах диапазона 0-9), то выполняется сравнение с пятеркой и указывается в массиве ключей.
Пример использования
echo numberEnd(7, 'удав', array('', 'а', 'ов'));
7 удавов
echo numberEnd(1, 'запис', array('ь', 'и', 'ей'));
1 запись
Удачи!
comments powered by HyperComments