fork download
  1. <?php
  2.  
  3.  
  4. /* Возвращает соответствующую числу форму слова: 1 рубль, 2 рубля, 5 рублей */
  5. function inclineWord($number, $word1, $word2, $word3) {
  6.  
  7. if ($number % 100 > 10 and $number % 100 < 20) {
  8. $number %= 100;
  9. } elseif ($number > 0) {
  10. $number %= 10;
  11. }
  12.  
  13. if ($number == 1) {
  14. $word = $word1;
  15. } elseif ($number >= 2 and $number <= 4) {
  16. $word = $word2;
  17. } elseif ($number >= 5 and $number <= 9 or $number > 10 and $number < 20 or $number == 0) {
  18. $word = $word3;
  19. }
  20.  
  21. return $word;
  22. }
  23.  
  24. /*
  25.   Преобразует числа от 0 до 999 в текст. Параметр $isFemale равен нулю,
  26.   если мы считаем число для мужского рода (один рубль),
  27.   и 1 — для женского (одна тысяча). Параметр $totalNumberLength
  28.   помогает определить число ноль.
  29. */
  30. function smallNumberToText($number, $isFemale, $totalNumberLength) {
  31.  
  32. $spelling = array(
  33. 0 => 'ноль', 10 => 'десять', 100 => 'сто',
  34. 1 => 'один', 11 => 'одиннадцать', 20 => 'двадцать', 200 => 'двести',
  35. 2 => 'два', 12 => 'двенадцать', 30 => 'тридцать', 300 => 'триста',
  36. 3 => 'три', 13 => 'тринадцать', 40 => 'сорок', 400 => 'четыреста',
  37. 4 => 'четыре', 14 => 'четырнадцать', 50 => 'пятьдесят', 500 => 'пятьсот',
  38. 5 => 'пять', 15 => 'пятнадцать', 60 => 'шестьдесят', 600 => 'шестьсот',
  39. 6 => 'шесть', 16 => 'шестнадцать', 70 => 'семьдесят', 700 => 'семьсот',
  40. 7 => 'семь', 17 => 'семнадцать', 80 => 'восемьдесят', 800 => 'восемьсот',
  41. 8 => 'восемь', 18 => 'восемнадцать', 90 => 'девяносто', 900 => 'девятьсот',
  42. 9 => 'девять', 19 => 'девятнадцать'
  43. );
  44.  
  45. if ($isFemale) {
  46. $femaleSpelling = array(
  47. 1 => 'одна',
  48. 2 => 'две'
  49. );
  50. $spelling = array_replace($spelling, $femaleSpelling);
  51. }
  52.  
  53. if ($number > 0) {
  54.  
  55. $lengthOfNumber = floor(log10($number) + 1);
  56.  
  57. // Разделение числа на единичный массив
  58. for ($i = 0; $i < $lengthOfNumber; $i++) {
  59. // Объединение чисел с особой формой
  60. if ($i == 0 and $number % 100 > 10 and $number % 100 < 20) {
  61. $numbers[] = ($number % 100);
  62. $number = floor($number / 100);
  63. } else {
  64. $numbers[] = ($number % 10);
  65. $number = floor($number / 10);
  66. }
  67. }
  68.  
  69. $numbers = array_reverse($numbers);
  70. $arraySize = count($numbers);
  71. /*
  72.   Подбор множителя, с его помощью из словаря запрашиваются сотни/десятки.
  73.  
  74.   Например, если размер ранее полученного массива с числами равен двум
  75.   и длина числа тоже равна двум, то множитель устанавливает значение 10.
  76.   В цикле, которой следует ниже, после итерации множитель уменьшается до 1.
  77.   */
  78. $mult = ($arraySize > 1) ? (($lengthOfNumber == 3) ? 100 : 10) : 1;
  79.  
  80. /* Берет по порядку значения из массива, делает запрос в словарь
  81.   и записывает полученное текстовое значение в массив $words */
  82. for ($i = 0; $i < $arraySize; $i++) {
  83. if ($numbers[$i] != 0) {
  84. $words[] = $spelling[$numbers[$i] * $mult];
  85. }
  86. // Уменьшение множителя для следующей итерации
  87. $mult = ($lengthOfNumber == 3 and $arraySize == 2) ? 1 : $mult / 10;
  88. }
  89.  
  90. $text = implode(' ', $words);
  91.  
  92. } elseif ($totalNumberLength < 1) {
  93. $text = $spelling[$number];
  94. } else {
  95. $text = null;
  96. }
  97.  
  98. return $text;
  99. }
  100.  
  101. function numberToText($number) {
  102.  
  103. $spelling = array(
  104. 0 => array(0 => 'рубль', 1 => 'рубля', 2 => 'рублей'),
  105. 1 => array(0 => 'тысяча', 1 => 'тысячи', 2 => 'тысяч'),
  106. 2 => array(0 => 'миллион', 1 => 'миллиона', 2 => 'миллионов')
  107. );
  108.  
  109. $lengthOfNumber = floor(log10($number) + 1);
  110.  
  111. $divisibleNumber = $number;
  112. // Цикл выполняется N-е кол-во раз в зависимости от длины числа или один раз для обработки нуля
  113. for ($x = 0; $x < ceil($lengthOfNumber / 3) or $x == 0; $x++) {
  114.  
  115. // Делит число на массив по три единицы
  116. $numbers[] = $divisibleNumber % 1000;
  117. $divisibleNumber = floor($divisibleNumber / 1000);
  118.  
  119. // Берет от тысячного числа в массиве $numbers последнюю цифру и проверяет на женственный род
  120. $isFemale = ($x == 1 and $numbers[1] % 10 == 1 or $x == 1 and $numbers[1] % 10 == 2) ? 1 : 0;
  121.  
  122. $numberInText = smallNumberToText($numbers[$x], $isFemale, $lengthOfNumber);
  123. $inclinedWord = inclineWord($numbers[$x], $spelling[$x][0], $spelling[$x][1], $spelling[$x][2]);
  124.  
  125. // Формирование и запись результата
  126. if ($x == 0) {
  127. if ($numberInText) {
  128. $text = $numberInText;
  129. }
  130. if (isset($text)) {
  131. $text = $text.' '."($number)".' '.$inclinedWord;
  132. } else {
  133. $text = "($number)".' '.$inclinedWord;
  134. }
  135. } else {
  136. if ($numberInText) {
  137. $text = $numberInText.' '.$inclinedWord.' '.$text;
  138. }
  139. }
  140. }
  141.  
  142. return $text;
  143. }
  144.  
  145. /* Вызовем функцию несколько раз */
  146.  
  147. $amount1 = mt_rand(1,99999999);
  148. $text1 = numberToText($amount1);
  149.  
  150. echo "На вашем счету {$text1}\n";
  151.  
  152. $amount2 = mt_rand(1,99999999);
  153. $text2 = numberToText($amount2);
  154.  
  155. echo "На вашем счету {$text2}\n";
  156.  
  157. $amount3 = mt_rand(1,99999999);
  158. $text3 = numberToText($amount3);
  159.  
  160. echo "На вашем счету {$text3}\n";
  161.  
  162. $numbers = [999999999, 0, 1, 11012013, 7000008, 1002, 1000, 7000000];
  163. foreach ($numbers as $number) {
  164. $amount4 = $number;
  165. $text4 = numberToText($amount4);
  166.  
  167. echo "На вашем счету {$text4}\n";
  168. }
Success #stdin #stdout 0.03s 23988KB
stdin
Standard input is empty
stdout
На вашем счету шестьдесят девять миллионов сто девяносто две тысячи двести семьдесят восемь (69192278) рублей
На вашем счету пятьдесят семь миллионов триста восемьдесят одна тысяча четыреста двадцать пять (57381425) рублей
На вашем счету тринадцать миллионов девяносто пять тысяч семьдесят (13095070) рублей
На вашем счету девятьсот девяносто девять миллионов девятьсот девяносто девять тысяч девятьсот девяносто девять (999999999) рублей
На вашем счету ноль (0) рублей
На вашем счету один (1) рубль
На вашем счету одиннадцать миллионов двенадцать тысяч тринадцать (11012013) рублей
На вашем счету семь миллионов восемь (7000008) рублей
На вашем счету одна тысяча два (1002) рубля
На вашем счету одна тысяча (1000) рублей
На вашем счету семь миллионов (7000000) рублей