fork download
  1. /*Во многих серьезных документах принято писать денежные суммы цифрами и прописью, вот так: «триста двадцать шесть (326)
  2. рублей», «две тысячи один (2001) рубль». Давай избавим людей от рутинной работы, и поручим склонение слов роботам и
  3. языку PHP.
  4.  
  5. Дана сумма, находящаяся в банке на счету, в рублях. Вывести ее в текстовом виде вроде "шестнадцать миллионов десять
  6. тысяч три (16010003) рубля".
  7. */
  8. <?php
  9. //mb_internal_encoding("utf-8");
  10. function amountOfDigits(int $number): int
  11. {
  12. return intval(log10(abs($number))) + 1;//Количество цифр = log10(n) + 1;
  13. }
  14.  
  15. function getFirstDigits(int $number, int $i): int
  16. {//Возвращает первые цифры для переданного числа
  17. return intval(floor($number / pow(10, $i)));
  18. }
  19.  
  20. function getRemainder(int $number, int $i): int
  21. {//Возвращает остаток числа
  22. return intval(floor($number % pow(10, $i)));
  23. }
  24.  
  25. function word(int $number, array $words): string //Возвращает "рубль", "рубля" или "рублей"
  26. {
  27. if ($number % 10 == 1 && $number != 11) {
  28. return $words[0];
  29. } elseif ($number % 10 >= 2 && $number % 10 < 5 && ($number % 100 > 15 || $number % 100 < 5)) {
  30. return $words[1];
  31. } else {
  32. return $words[2];
  33. }
  34. }
  35.  
  36. function digitsToWords(int $number, bool $isFemale): string
  37. {//Проверяет сотни, десятки и единицы и возвращает их, если они != 0
  38. $numbers = ["ноль", "один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь", "девять", "десять",
  39. "одиннадцать", "двенадцать", "тринадцать", "четырнадцать", "пятнадцать", "шестнадцать", "семнадцать", "восемнадцать", "девятнадцать",
  40. "двадцать", 30 => "тридцать", 40 => "сорок", 50 => "пятьдесят", 60 => "шестьдесят", 70 => "семьдесят", 80 => "восемьдесят", 90 => "девяносто",
  41. 100 => "сто", 200 => "двести", 300 => "триста", 400 => "четыреста", 500 => "пятьсот", 600 => "шесьтсот", 700 => "семьсот", 800 => "восемьсот", 900 => "девятьсот"];
  42. if ($number == 0) {
  43. return $numbers[$number];
  44. }
  45. $femNumbers = [1 => "одна", "две"];
  46. $resultExp = [];
  47. $hundred = intval(floor($number / 100) * 100);//Определяем количество сотен
  48. $tensAndUnits = $number % 100;
  49. $units = $tensAndUnits % 10;
  50.  
  51. if ($hundred >= 100) {
  52. $resultExp[] = $numbers[$hundred];
  53. }
  54. if ($tensAndUnits != 0) {
  55. if ($tensAndUnits > 9 && $tensAndUnits <= 20) {//Если число в этом диапазоне, то нет необходимости писать единицы
  56. $resultExp[] = $numbers[$tensAndUnits];
  57. } else {
  58. $tens = intval(floor($tensAndUnits / 10)) * 10;
  59. if ($tens != 0) {
  60. $resultExp[] = $numbers[$tens];
  61. }
  62. if ($units != 0) {
  63. if ($isFemale && ($units == 1 || $units == 2)) {//На жр нужно заменять только 1 или 2, и только перед словом тысяча(и)
  64. $resultExp[] = $femNumbers[$units];
  65. } else {
  66. $resultExp[] = $numbers[$units];
  67. }
  68. }
  69. }
  70. }
  71. return implode(" ", $resultExp);
  72. }
  73.  
  74. //Первый элемент при 1, 2-ой при 2-4, 3 при остальных
  75. $thousands = ["тысяча", "тысячи", "тысяч"];
  76. $millions = ["миллион", "миллиона", "миллионов"];
  77. $billions = ["миллиард", "миллиарда", "миллиардов"];
  78. $rubles = ["рубль", "рубля", "рублей"];
  79. $number = 987123;// миллиардах вместо 909123000 возвращается 614155704
  80. $resultExp = [];//Здесь хранится результат
  81. //echo PHP_INT_MAX . "\n";
  82. if ($number == 0) {
  83. $resultExp[] = digitsToWords($number, false);
  84. $resultExp[] = word($number, $rubles);
  85. }
  86. while ($number >= 1) {
  87. $isFemale = false;//Женский род
  88. $amountOfDigits = amountOfDigits($number);
  89. $denomination = [];//В зависимости от количества цифр здесь будут хранится тысячи, миллионы или миллиарды
  90. if ($amountOfDigits >= 4) {
  91. if ($amountOfDigits >= 4 && $amountOfDigits < 7) {
  92. $denomination = $thousands;
  93. $isFemale = true;
  94. } elseif ($amountOfDigits >= 7 && $amountOfDigits < 10) {
  95. $denomination = $millions;
  96. } else {
  97. $denomination = $billions;
  98. }
  99. $number = intval($number);
  100. while (1) {
  101. $firstDigits = getFirstDigits($number, ($amountOfDigits % 3 != 0) ? $amountOfDigits - $amountOfDigits % 3 : $amountOfDigits - 3);
  102. $number = getRemainder($number, ($amountOfDigits % 3 != 0) ? $amountOfDigits - $amountOfDigits % 3 : $amountOfDigits - 3);
  103. $resultExp[] = digitsToWords($firstDigits, $isFemale);
  104. $resultExp[] = word($firstDigits, $denomination);
  105. break;
  106. }
  107. } else {
  108. $resultExp[] = digitsToWords($number, $isFemale);
  109. $resultExp[] = word($number, $rubles);
  110. break;//Выходим из цикла, т.к. уже расписали все цифры
  111. }
  112. }
  113.  
  114. echo "Result: " . implode(" ", $resultExp) . "\n";
  115. ?>
Success #stdin #stdout 0s 82560KB
stdin
Standard input is empty
stdout
/*Во многих серьезных документах принято писать денежные суммы цифрами и прописью, вот так: «триста двадцать шесть (326)
рублей», «две тысячи один (2001) рубль». Давай избавим людей от рутинной работы, и поручим склонение слов роботам и
языку PHP.

Дана сумма, находящаяся в банке на счету, в рублях. Вывести ее в текстовом виде вроде "шестнадцать миллионов десять
тысяч три (16010003) рубля".
*/
Result: девятьсот восемьдесят семь тысяч сто двадцать три рубля