NAME

Lingua::RU::Numeral - Perl extension for generate Russian wording of numerals from the natural numbers and 0 (zero).

SYNOPSIS

Activate the module:

use Lingua::RU::Numeral qw( num2cardinal case_endings spelled_out_number );

or

use Lingua::RU::Numeral qw(:all);

Usage examples:

  1. Using with default options, i.e. 'nominative' case (Именительный падеж), 'masculine' gender (Мужской род), numeral in 'singular' (единственное число), 'inanimate' object (неодушевлённый предмет):

    say num2cardinal('930651342187216');

    Will print the result:

    девятьсот тридцать триллионов шестьсот пятьдесят один миллиард триста сорок два миллиона сто восемьдесят семь тысяч двести шестнадцать
  2. Using 'feminine' gender (Женский род), and with other default options:

    say num2cardinal('101101102101101', 'gender'=>'feminine');

    Will print the result:

    сто один триллион сто один миллиард сто два миллиона сто одна тысяча сто одна
  3. Using 'neuter' gender (Средний род), and with other default options:

    say num2cardinal('101101102101101', 'gender'=>'neuter');

    Will print the result:

    сто один триллион сто один миллиард сто два миллиона сто одна тысяча сто одно
  4. Using 'genitive' case (Родительный падеж), and with other default options:

    say num2cardinal( 1000003, 'case'=>'genitive');

    or abbreviated form

    say num2cardinal( 1000003, 'case'=>'g');

    Will print the result:

    одного миллиона трёх
  5. Using 'accusative' case (Винительный падеж), 'feminine' gender (Женский род, abbreviated form), 'animate' object (одушевлённый предмет), and with other default option, i.e. 'singular' (единственное число):

    say num2cardinal( 2, 'case'=>'accusative', 'gender'=>'f', 'object'=>'animate');

    Will print the result:

    двух
  6. Using 'accusative' case (Винительный падеж, abbreviated form), 'plural' (множественное число), 'inanimate' object (неодушевлённый предмет, by default), and with other default options:

    say num2cardinal( 1000, 'case'=>'a', 'multi'=>'plural');

    Will print the result:

    одни тысячи
  7. Using 'accusative' case (Винительный падеж, abbreviated form), 'plural' (множественное число, abbreviated form), 'animate' object (одушевлённый предмет), and with other default options:

    say num2cardinal( 1000, 'case'=>'a', 'multi'=>'p', 'object'=>'animate');

    Will print the result:

    одних тысяч
  8. Using reference 'epilog' with other default options:

    say num2cardinal( 1000, 'epilog'=>'RUB');	# add 'рубль' (российский), using an alphabetic currency code
    say num2cardinal( 1000, 'epilog'=> 643 );	# the same, using a digital currency code
    say num2cardinal( 2000, 'epilog'=>'rub');	# add 'копейка' (российская)
    say num2cardinal( 2000, 'epilog'=> -643);	# the same
    say num2cardinal( 1000, 'epilog'=>'BYR');	# add 'белорусский рубль', using an alphabetic currency code

    Will print the results:

    одна тысяча рублей
    одна тысяча рублей
    две тысячи копеек
    две тысячи копеек
    одна тысяча белорусских рублей
  9. Using custom 'epilog' which is configured manually (норвежская крона) with other default options:

    my $epilog = { # Nominative case (Именительный падеж)
                 'object' => 'inanimate',
                 'gender' => 'feminine',
                 'root'   => ['норвежск','крон'],
                 'ends'   => [ ['их','ая', ('их') x 5 ], ['','а', ('ы') x 3, ('') x 2] ],
                };
    
    say num2cardinal( $_,
                     'epilog' => $epilog
                    ) for 0..5, 10, 100, 1000;

    Will print the result:

    ноль норвежских крон
    одна норвежская крона
    две норвежских кроны
    три норвежских кроны
    четыре норвежских кроны
    пять норвежских крон
    десять норвежских крон
    сто норвежских крон
    одна тысяча норвежских крон
  10. Using 'prolog' and 'epilog' with other explicit and implicit options:

    say num2cardinal( 11,
                     'case'   => 'p',	# Предложный: о ком? о чём?
                     'prolog' => 'о',
                     'epilog' => 'stamp',
                    );

    OR the same with details:

    my $epilog = {
                 'object' => 'inanimate',
                 'gender' => 'feminine',
                 'root'   => ['печат'],
                 'ends'   => [ ['ях','и', ('ях') x 5 ] ],
                };
    
    say num2cardinal( 11,
                     'case'   => 'prepositional',	# Предложный: о ком? о чём?
                     'prolog' => ['о','об=од'],
                     'epilog' => $epilog,
                    );

    Will print the result:

    об одиннадцати печатях
  11. Using 'alt' (alternate form) with other default options:

    say num2cardinal( 0 );
    say num2cardinal( 0, alt => { 0=>'TRUE'} );

    Will print the results:

    ноль
    нуль
  12. Using 'ucfirst' with other explicit and implicit options:

    say num2cardinal( 11, 'ucfirst' => 'TRUE');
    say num2cardinal( 11, case => 'p', prolog => 'о' );
    say num2cardinal( 11, case => 'p', prolog => 'о', 'ucfirst' => 1 );
    say num2cardinal( 11, case => 'p', prolog => 'о', epilog => 'RUB', 'ucfirst' => 1 );

    Will print the results:

    Одиннадцать
    об одиннадцати
    об Одиннадцати
    об Одиннадцати рублях
  13. Usage for correct case endings only (without numeral written as a string):

    my $number = 1000;
    my %options = ('prolog' => 'за', 'epilog'=>'CNY');
    
    say case_endings( $number, %options);	# add 'юань' (Chinese yuan), using an alphabetic currency code

    or in verbose form:

    my( $i, $ns, @s ) = &num2cardinal( $number, %options );
    splice @s, $i, $ns - $i + 1, $number;
    say join(' ', @s);

    Will print the results:

    за 1000 юаней
  14. Usage for correct case endings only (without numeral written as a string):

    say spelled_out_number( 100_000, case=>'accusative', 'prolog'=>'за', 'epilog'=>'CNY', 'ucfirst'=>1 );

    Will print the results:

    за 100000 (Сто тысяч) юаней

LIMITATIONS

num2cardinal() subroutine generates Russian cardinal numbers for the natural numbers and 0 (zero), i.e. from 0 to 999_999_999_999_999, e.g.:

say num2cardinal( 0 );
say num2cardinal( 0, 'case' => 'instrumental');
say num2cardinal('999999999999999');
say num2cardinal('1000000000000000');

Will print the results:

ноль
нолём
девятьсот девяносто девять триллионов девятьсот девяносто девять миллиардов девятьсот девяносто девять миллионов девятьсот девяносто девять тысяч девятьсот девяносто девять
1000000000000000 > 999_999_999_999_999 !

The target Cyrillic character set (returns) is UTF-8 (use utf8).

This module have reason only for perl 5.10 and higher.

ABSTRACT

This module provides functions that can be used to generate Russian verbiage for the natural numbers (unsigned integer) and 0 (zero). The methods implemented in this module, are all focused on knowledge of Russian grammar.

DESCRIPTION

This module provides functions that can be used to generate Russian verbiage for the natural numbers (unsigned integer) and 0 (zero). The methods implemented in this module, are all focused on knowledge of Russian grammar.

This module makes verbiage in "short scales" (1,000,000,000 is "один миллиард" rather than "одна тысяча миллионов"). For details see this Wikipedia russian article:

https://ru.wikipedia.org/wiki/Системы_наименования_чисел

SUBROUTINES

Lingua::RU::Numeral provides these subroutines:

num2cardinal( $number [, %facultative_options ] );
case_endings( $number [, %facultative_options ] );
spelled_out_number( $number [, %facultative_options ] );

num2cardinal( $number [, %facultative_options ] )

Convert a $number (natural numbers or 0) to Russian text (string) made in a particular calling context (list, scalar or void), using explicitly specified global %facultative_options, otherwise - default options.

num2cardinal() returns ($i, $ns, @s) if the currently executing subroutine expects to return a list value, and Russian $text if it is looking for a scalar value. Here $i — index of the first numeral word in the array of words @s; $ns — index of the last numeral word in @s; @s — the array of words that form the returned Russian text (string) in scalar context, e.g. join(' ',@s).

The following can be global %facultative_options:

  • 'case' option — case of a numeral can take the following meanings (case names can be shorthand to one first letter):

    1. 'n'|'nominative' (Именительный падеж: есть кто? что? is default),
    2. 'g'|'genitive' (Родительный падеж: нет кого? чего?),
    3. 'd'|'dative' (Дательный падеж: рад кому? чему?),
    4. 'a'|'accusative' (Винительный падеж: вижу кого? что?),
    5. 'i'|'instrumental' (Творительный падеж: оплачу кем? чем?),
    6. 'p'|'prepositional' (Предложный падеж: думаю о ком? о чём?).
  • 'gender' option — 'm'|'masculine' (Мужской род, by default) or 'f'|'feminine' (Женский род) or 'n'|'neuter' (Средний род). Gender names can be shorthand to one first letter also.

  • 'multi' option — word(s) in the plural ('1'|'plural', множественное число) or 'undef'|'0'|'singular' (единственное число, by default).

  • 'object' option — 'i'|'inanimate' (неодушевлённый предмет, by default) or 'a'|'animate' (одушевлённый предмет) object. Object names can be shorthand to one first letter also.

  • 'prolog' option — PREPosition(s) of the numeral is the REF to ARRAY, where 0th element ('PREP_0') — the preposition for all numerals, except for those indicated by subsequent array elements ('PREP_x') as ['PREP_0','PREP_1=REGEX',...].

    Here REGEX — the regular expression that is used to find a match at the beginning of a numeric string like: numeral =~/^REGEX/. For example:

    'prolog' => ['о','об=од']

    If 'prolog' is SCALAR value (e.g. 'prolog'=>'о') then it is used from internal reference list of prologs (inner prolog). In this case, the inner prolog controls case of the numeral and overrides (suppresses or affirms its authority) the global option 'case'.

    Now internal reference list of prologs contains the following preconfigured phrase structures, i.e. the inner prolog:

    • for genitive case (Родительный падеж):

      без, безо, вблизи, ввиду, вдоль, взамен, вкруг, вместо, вне, внизу, внутри, внутрь, вперед, вследствие, впереди, вроде, вовнутрь, возле, вокруг, вследствие, выше, для, до, из, изо, из-за, изнутри, из-под, из-подо, касаемо, касательно, кроме, кругом, мимо, накануне, наместо, наподобие, напротив, насупротив, насчет, ниже, обок, обочь, около, окрест, округ, опричь, от, ото, относительно, поблизости, поверх, подле, позади, позадь, помимо, поперек, посереди, посередине, после, посередь, посреди, посредине, посредством, превыше, против, путем, ради, сверх, сверху, свыше, середь, сзади, силами, снаружи, снизу, спереди, среди, средь, супротив, у — equivalent to the corresponding word, specified as the only array element.

    • for dative case (Дательный падеж):

      вдогон, вдогонку, вдогоночку, вослед, вразрез, вслед, к, ко, наперекор, наперерез, подобно, противно, сообразно, соответственно, соразмерно — equivalent to the corresponding word, specified as the only array element.

    • for accusative case (Винительный падеж):

      включая, выключая, исключая, про, сквозь, спустя, через, чрез — equivalent to the corresponding word, specified as the only array element.

    • for instrumental case (Творительный падеж):

      кончая, над, надо, начиная, перед, передо, по-за, по-над — equivalent to the corresponding word, specified as the only array element.

    • for prepositional case (Предложный падеж):

      при — equivalent to ['при'].

    • for genitive (Родительный) and dative cases (Дательный падеж):

      согласно — equivalent to ['согласно'].

    • for genitive (Родительный) and instrumental cases (Творительный падеж):

      меж, между, промеж, промежду — equivalent to the corresponding word, specified as the only array element.

    • for accusative (Винительный) and instrumental cases (Творительный падеж):

      за, под, подо — equivalent to the corresponding word, specified as the only array element.

    • for dative (Дательный падеж) and accusative cases (Винительный падеж):

      благодаря — equivalent to ['благодаря'].

    • for accusative (Винительный) and prepositional cases (Предложный падеж):

      на — equivalent to ['на'].

      o, , oбо — equivalent to ['о','об=од'].

      в, во — equivalent to ['в'] and ['во'], respectively.

    • for genitive (Родительный), accusative (Винительный), and instrumental cases (Творительный падеж):

      c, со — equivalent to ['с','со=ст'].

    • for dative (Дательный), accusative (Винительный), and prepositional cases (Предложный падеж):

      по — equivalent to ['по'].

    WARNING! Once again, the inner prolog controls case of the numeral and overrides (suppresses or affirms its authority) the global option 'case'.

  • 'epilog' option — final word(s) (phrase(s)) of the numeral is SCALAR value (name) from internal reference list of epilogs or the REF to complex HASH to create a custom phrase(s).

    Internal reference list of epilogs contains the following preconfigured phrase structures:

    • RUB|RUR|643|810|₽|рубль|ruble — for Russian ruble (Российский рубль); rub|rur|-643|-810|byb|byr|byn|\-933|\-974|копейка|kopek — for kopek (копейка).

    • CNY|RMB|156|юань|yuan — Chinese yuan; cny|rmb|-156|фынь — for Chinese cent.

    • USD|840|US$|$|доллар|dollar — for United States dollar; usd|-840|цент|cent — for US cent.

    • BYR|BYB|BYR|BYN|Br|933|974 — for Belarusian ruble (Белорусский рубль).

    • Time measures: 'year|год|лет'; 'month|месяц'; 'day|день'; 'hour|час'; 'min|мин' — for minute (минута); 'sec|сек' — for second (секунда).

    • Miscellaneous: 'meter|метр'; 'stamp|печать'.

    The custom 'epilog' presents the REF to HASH with complex structure of SCALAR values and ARRAYs. For example, год, лет (shorthand equivalent is $epilog = 'year' for 'nominative' case (Именительного падежа):

    my $epilog = {
                 'object' => 'inanimate', # неодушевлённый предмет
                 'gender' => 'masculine', # Мужской род
                 'root'   => [''],
                 'ends'   => [['лет','год', ('года') x 3, ('лет') x 2 ]],
                };

    or for секунда (shorthand equivalent is $epilog = 'sec.' for 'accusative' case (Винительного падежа)):

    my $epilog = {
                 'object' => 'inanimate',
                 'gender' => 'feminine', # Женский род
                 'root'   => ['секунд'],
                 'ends'   => [['','у', ('ы') x 3, ('') x 2 ]],
                };

    or for рубль (shorthand equivalent is $epilog = 'RUB' for 'dative' case (Дательного падежа)):

    my $epilog = {
                 'object' => 'inanimate',
                 'gender' => 'masculine', # Мужской род
                 'root'   => ['рубл'],
                 'ends'   => [['ям','ю', ('ям') x 4, 'ей']],
                };

    Here are:

    • already known 'object' and 'gender' options. These options are recommended but not required. WARNING! These options take precedence over the global options('object', 'gender'), i.e. override them.

    • 'root' option means the 'epilog' root, i.e. common invariable part of the custom 'epilog' words (or its absence in the form of "").

    • 'ends' option means the 'epilog' word endings for seven (7) numerals: 0, 1, 2, 3, 4, 5, 1000 (thousand) respectively. In fact, the seventh ending in each subarray also corresponds to a million (1_000_000), a billion (1_000_000_000), and a trillion (1_000_000_000_000).

  • 'alt' option — REF to HASH of alternative (colloquial, obsolete) word forms. Currently available for:

    • zero (0) (ноль, by default; 'alt' => {0=>1}, to obtain нуль).

    • 'i.T' key — Colloquial or Obsolete form for 'thousands' (тысяч) in 'instrumental' cases (Творительный падеж):

      say num2cardinal( 1000, case => 'i', alt => {'i.T'=>'Colloquial'} ); # or 'i.T'=>'C'
      say num2cardinal( 1000, case => 'i', alt => {'i.T'=>'Obsolete'} ); # or 'i.T'=>'O'
      say num2cardinal( 1000, case => 'i'); # traditional established form

      Will print the results:

      одной тысячью
      одной тысячею
      одной тысячей
    • 'i.8' key — сolloquial form for 'восьмью', 'восьмьюдесятью', 'восьмьюстами' in 'instrumental' cases (Творительный падеж):

      say num2cardinal( $_, case => 'i', alt => {'i.8'=>'TRUE'} ) for 8000, 80, 800;

      Will print the results:

      восьмью тысячами
      восьмьюдесятью
      восьмьюстами

      Instead traditional established forms:

      восемью тысячами
      восемьюдесятью
      восемьюстами
    • 'if1' key — alternate form for 'одною' in 'instrumental' cases (Творительный падеж) and 'feminine' gender:

      say num2cardinal( 1000, case => 'i', gender => 'feminine', alt => {'if1'=>'TRUE'} );
      say num2cardinal( 1000, case => 'i', gender => 'feminine', alt => {'if1'=>'TRUE', 'i.T'=>'O'} ); # alternate and obsolete form
      
      одною тысячей
      одною тысячею
  • 'ucfirst' option — returns the numeral with the first character capitalized (Upper case). WARNING! does not affect the 'prolog'.

case_endings( $number [, %facultative_options ] )

This subroutine returns the 'epilog' corresponding to the numeral and case endings.

This subroutine is only intended to match 'epilog' case endings. It does NOT convert a $number (natural numbers or 0) to Russian text (string, i.e. a numeral). Therefore, this subroutine makes sense when at least $number and 'epilog' option are given. All global %facultative_options, are the same as num2cardinal() subroutine. In fact, this subroutine is a wrapper around the num2cardinal() subroutine with an additional parameter case_endings:

say case_endings( 1000, 'epilog'=>'RUB');

Will print the results:

1000 рублей

spelled_out_number( $number [, %facultative_options ] )

This subroutine returns the $number that is padded with Russian numeral in parentheses (text string). E.g.:

say spelled_out_number( 1000, case=>'accusative', 'prolog'=>'за', 'epilog'=>'CNY', 'ucfirst'=>1 );

Will print the results:

за 1000 (Одну тысячу) юаней

EXPORT

Lingua::RU::Numeral exports nothing by default. Each of the subroutines can be exported on demand, as in

use Lingua::RU::Numeral qw( num2cardinal );

and the tag all exports them all:

use Lingua::RU::Numeral qw( :all );

DEPENDENCIES

Lingua::RU::Numeral is known to run under perl 5.10.0 on Linux.

CAVEATS

The author of this module is not linguist. If you would like to help me correct numeral errors, please send me an email.

SEE ALSO

Igor' A. Mel'čuk. THE SURFACE SYNTAX OF RUSSIAN NUMERAL EXPRESSIONS. -Wien: Volume 16 of Wiener slawistischer Almanach, Institut für Slavistik der Universität, -1985. — 514 p. ISSN 0258-6819.

Мельчук, И.А. Поверхностный синтаксис русских числовых выражений. -Wien: Volume 16 of Wiener slawistischer Almanach, Institut für Slavistik der Universität, -1985. — 514 c. ISSN 0258-6819.

Сичинава, Д.В. Числительные // Материалы к корпусной грамматике русского языка. Выпуск III : Части речи и лексико-грамматические классы. СПб.: Нестор-История, 2018. С. 193–257.

Сичинава, Д.В. Предлоги // Материалы к корпусной грамматике русского языка. Выпуск III : Части речи и лексико-грамматические классы. СПб.: Нестор-История, 2018. С. 329–373.

Lingua::RU::Number is a Perl module that offers some similar functionality.

AUTHOR

Alessandro N. Gorohovski, <an.gorohovski@gmail.com>

COPYRIGHT AND LICENSE

Copyright (C) 2022-2023 by Alessandro N. Gorohovski

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available.