Archive

Archive for the ‘русский язык’ Category

Русский Язык. Выбор окончаний

April 9th, 2010 No comments

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

Например: “Комментариев: 4″, “Новых писем: 1″, “Всего сотрудников: 19″ и т.д.

Пользователь – существо, как правило, неприхотливое. Для пользователя программа – магия. И если она работает, то уже хорошо, главное – покажите куда нажимать.

Но если вы все же найдете свободную минутку, чтобы его порадовать, то почему бы не сделать так: “4 комментария“, “1 новое письмо“, “Всего 19 сотрудников” и т.д.

В английском языке все просто: “1 comment”, “N comments” (N > 1). Богатство же Русского Языка не дает скучать хмурым программистам. Статья посвящена правильному выбору окончаний.

Давайте возьмем слово “сообщение” и пробежимся по первой десятке чисел.

  • 0 сообщений
  • 1 сообщение
  • 2 сообщения
  • 3 сообщения
  • 4 сообщения
  • 5 сообщений
  • 6 сообщений
  • 7 сообщений
  • 8 сообщений
  • 9 сообщений

Можно выделить три группы, я назову их w1, w2 и w5.

Группа w1:

  • 1 сообщение

Группа w2:

  • 2 сообщения
  • 3 сообщения
  • 4 сообщения

Группа w5:

  • 5 сообщений
  • 6 сообщений
  • 7 сообщений
  • 8 сообщений
  • 9 сообщений
  • 0 сообщений

Для любого числа подходящая пара будет относится к одной из этих трех групп. Но как обобщить правило для всех чисел?

Первая мысль, которая приходит в голову – брать последнюю цифру. Действительно: “1021 сообщение”, “542 сообщения”, “35 сообщений”. Но эта мысль верна ровно на 90%.

Дело в том, что все числа, предпоследняя цифра которых равна единице, отностяся к группе w5: “11 сообщений”, “1012 сообщений”.

Теперь можно сформулировать правило выбора группы для любого числа:

  • w5, если предпоследняя цифра равна единице
  • или w5, если последняя цифра больше или равна пяти
  • или w5, если последняя цифра равна нулю
  • или w1, если последняя цифра равна единице
  • иначе w2

Ниже несколько реализаций функции.

PHP:

//
// Функция выбирает нужное слово для конкретного числа.
// Например: 1 сообщение, 2 сообщения, 5 сообщений.
//
function NumberOf($number, $w1, $w2, $w5, $appendNumber = true)
{
	$n1 = $number % 10;   // 123 % 10 = 3
	$n12 = $number % 100; // 123 % 100 = 23
 
	if ($n1 >= 5 || $n1 == 0 || ($n12 >= 11 && $n12 <= 19))
		$w = $w5;
	else if ($n1 == 1)
		$w = $w1;
	else
		$w = $w2;
 
	return $appendNumber ? "$number $w" : $w;
}

Пример использования:

$n = 10;
 
echo NumberOf($n, 'новое сообщение', 'новых сообщения', 'новых сообщений');
 
echo "<b>$n</b>" .
       NumberOf($n, 'новое сообщение', 'новых сообщения', 'новых сообщений', false);

Результат:

10 новых сообщений
<b>10</b> новых сообщений

Java Script:

//
// Функция выбирает нужное слово для конкретного числа.
// Например: 1 сообщение, 2 сообщения, 5 сообщений.
//
function numberOf(number, w1, w2, w5, appendNumber)
{
	var w = '';
	var n1 = number % 10;   // 123 % 10 = 3
	var n12 = number % 100; // 123 % 100 = 23
 
	if (n1 >= 5 || n1 == 0 || (n12 >= 11 && n12 <= 19))
		w = w5;
	else if (n1 == 1)
		w = w1;
	else
		w = w2;
 
	if (appendNumber == null)
		appendNumber = true;
 
	return appendNumber ? (number + ' ' + w) : w;
}

Пример использования:

var n = 10;
alert numberOf(n, 'новое сообщение', 'новых сообщения', 'новых сообщений');
alert numberOf(n, 'новое сообщение', 'новых сообщения', 'новых сообщений', false);

C#:

//
// Функция выбирает нужное слово для конкретного числа.
// Например: 1 сообщение, 2 сообщения, 5 сообщений.
//
static string NumberOf(int number,
                       string w1,
                       string w2,
                       string w5,
                       bool appendNumber)
{
	string w = "";
	int n1 = number % 10;   // 123 % 10 = 3
	int n12 = number % 100; // 123 % 100 = 23
 
	if (n1 >= 5 || n1 == 0 || (n12 >= 11 && n12 <= 19))
		w = w5;
	else if (n1 == 1)
		w = w1;
	else
		w = w2;
 
	return appendNumber ? (number.ToString() + ' ' + w) : w;
}

Пример использования:

string s1, s2;
int n = 10;
 
s1 = NumberOf(n, "новое сообщение", "новых сообщения", "новых сообщений", true);
s2 = NumberOf(n, "новое сообщение", "новых сообщения", "новых сообщений", false);
 
Console.WriteLine(s1);
Console.WriteLine(s2);

Материал не претендует на революционность, хотя и является собственной разработкой. Я не искал решений в Интеренете, так как люблю изобретать велосипеды )