PHP как преобразовать число (год) в текст напр. 1996 = Девятнадцать девяносто шесть, а 2004 = Две тысячи четыре - PullRequest
1 голос
/ 19 июня 2020

У меня есть сертификат. Я хочу преобразовать год в текст, но в заданном формате

  convertYearToText(1994){
    return "Ninteen hundred ninty six";
    }
    convertYearToText(2004){
    return "two thousand four";
    }

У меня есть функция, но она дает мне Одна тысяча девятьсот девяносто шесть

 numberTowords(1996)
    {

        $num = str_replace(array(',', ' '), '' , trim($num));
        if(! $num) {
            return false;
        }
        $num = (int) $num;
        $words = array();
        $list1 = array('', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven',
            'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'
        );
        $list2 = array('', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety', 'hundred');
        $list3 = array('', 'thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion',
            'octillion', 'nonillion', 'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quattuordecillion',
            'quindecillion', 'sexdecillion', 'septendecillion', 'octodecillion', 'novemdecillion', 'vigintillion'
        );
        $num_length = strlen($num);
        $levels = (int) (($num_length + 2) / 3);
        $max_length = $levels * 3;
        $num = substr('00' . $num, -$max_length);
        $num_levels = str_split($num, 3);
        for ($i = 0; $i < count($num_levels); $i++) {
            $levels--;
            $hundreds = (int) ($num_levels[$i] / 100);
            $hundreds = ($hundreds ? ' ' . $list1[$hundreds] . ' hundred' . ' ' : '');
            $tens = (int) ($num_levels[$i] % 100);
            $singles = '';
            if ( $tens < 20 ) {
                $tens = ($tens ? ' ' . $list1[$tens] . ' ' : '' );
            } else {
                $tens = (int)($tens / 10);
                $tens = ' ' . $list2[$tens] . ' ';
                $singles = (int) ($num_levels[$i] % 10);
                $singles = ' ' . $list1[$singles] . ' ';
            }
            $words[] = $hundreds . $tens . $singles . ( ( $levels && ( int ) ( $num_levels[$i] ) ) ? ' ' . $list3[$levels] . ' ' : '' );
        } //end for loop
        $commas = count($words);
        if ($commas > 1) {
            $commas = $commas - 1;
        }
        return implode(' ', $words);
    }

Мне нужно, чтобы результат возврата был «девятнадцатьсот девяносто шесть», пожалуйста, помогите

Ответы [ 3 ]

0 голосов
/ 19 июня 2020

Я взял на себя смелость переписать и очистить вашу функцию, добавив одну важную часть: преобразование из

(a) One тысяча девятьсот девяносто шесть в (b ) Девятнадцатьсот девяносто шесть.

Теперь функция принимает необязательный второй аргумент $year. Если установлено значение true, оно вернет (b) , иначе (a) .

numberTowords(1996) даст (a)

numberTowords(1996,true) даст (b)

Комментарии в коде показывают, что я изменил

function numberTowords($num,$year=false){
    $num = str_replace(array(',', ' '), '' , trim($num));
    if($num==='')return false;
    
    $num = (int) $num;
    $words = [];
    $list=[
        1=>['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven',
        'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'],
        2=>['', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety', 'hundred'],
        3=>['', 'thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion','octillion', 'nonillion', 'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quattuordecillion','quindecillion', 'sexdecillion', 'septendecillion', 'octodecillion', 'novemdecillion', 'vigintillion']
        ];
    
    //$levels = number of parts of 3 
    $levels = ceil(strlen($num)/3);
    if($levels===0)return false;

    //$parts = parts of 3, first one left-padded with zeros
    $parts = str_split(substr('00' . $num, -$levels*3), 3);
    $part_count=count($parts);

    //THE IMPORTANT YEAR BIT
    //only if year-flag = true
    //only if no more then 2 parts
    //only if year < 9999
    // EXAMPLE: 1986
    $change = false; //<< === added flag
    if($year===true && $part_count===2 && $num<9999){
        //get the first digit of last part (ex: 9)
        $x=substr($parts[$part_count-1],0,1);
        //if first digit = 0 : skip
        //else: remove from last part and add to part before
        // ex: 001 => 0019 and 986 => 86
        if($x!=='0'){
            $parts[$part_count-2]=$parts[$part_count-2].$x;
            $parts[$part_count-1]=substr($parts[$part_count-1],1);
            }
        }

    //LOOP THE PARTS
    for ($i=0; $i < $part_count; $i++) {
        $w=[];
        //get the (int) of part
        $part_num=(int)$parts[$i];
    
        //HUNDREDS
        if($part_num >= 100){
            $w[]=$list[1][(int)substr($parts[$i],0,1)];
            $w[]=$list[2][10];
            }
        //TENS and SINGLES
        $remainder=$part_num%100;
        if($remainder>19){
            $w[]=$list[2][floor($remainder/10)];
            $w[]=$list[1][$remainder%10];
            }
        else{
            $w[]=$list[1][$remainder];
            }
                // << TEST FOR FLAG
        if($change===true && $i===0)
            $w[]=$list[2][10];
        else 
            $w[]=$list[3][$part_count - $i -1];
        
        $words[]=implode(' ',$w);
    } //end for loop
    return implode(' ', $words);
}
0 голосов
/ 20 июня 2020

Я предполагаю, что вы хотите следовать правилам грамматики и правописания:

  • Это нин e ty и nin e подросток, а не девяносто или девятнадцать .
  • Дефис необходим для написания чисел от 21 до 99, которые не кратны 10.

Кроме того, ваша функция имеет дело с числами, которые не имеют практического значения. диапазон лет, поэтому я бы предложил функцию, которая специально работает с числами в диапазоне от 1 до 9999, принимая во внимание два вышеуказанных момента:

function convertBelow100($pair) { // Helper function
    $text = ["", "one", "two", "three", "four", "five", "six", "seven", "eight",
             "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", 
             "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "thirty",
             "forty", "fifty", "sixty", "seventy", "eighty", "ninety"];
    return $pair < 20 ? $text[$pair] 
           : $text[18+floor($pair/10)] . ($pair%10 ? "-" . $text[$pair%10] : "");
}

function convertYearToText($year) { // Main algorithm
    $century = floor($year/100);
    return trim(($century%10 ? convertBelow100($century) . " hundred " 
                : ($year > 999 ? convertBelow100(floor($year/1000)) . " thousand " : "")
                ) . convertBelow100($year%100));
}
0 голосов
/ 19 июня 2020

Не могли бы вы просто использовать

$f = new NumberFormatter("en", NumberFormatter::SPELLOUT);
echo $f->format(1994);

Это также может помочь, если вы не хотите использовать плагин

function convertNumber($number)
{
    list($integer, $fraction) = explode(".", (string) $number);

    $output = "";

    if ($integer{0} == "-")
    {
        $output = "negative ";
        $integer    = ltrim($integer, "-");
    }
    else if ($integer{0} == "+")
    {
        $output = "positive ";
        $integer    = ltrim($integer, "+");
    }

    if ($integer{0} == "0")
    {
        $output .= "zero";
    }
    else
    {
        $integer = str_pad($integer, 36, "0", STR_PAD_LEFT);
        $group   = rtrim(chunk_split($integer, 3, " "), " ");
        $groups  = explode(" ", $group);

        $groups2 = array();
        foreach ($groups as $g)
        {
            $groups2[] = convertThreeDigit($g{0}, $g{1}, $g{2});
        }

        for ($z = 0; $z < count($groups2); $z++)
        {
            if ($groups2[$z] != "")
            {
                $output .= $groups2[$z] . convertGroup(11 - $z) . (
                        $z < 11
                        && !array_search('', array_slice($groups2, $z + 1, -1))
                        && $groups2[11] != ''
                        && $groups[11]{0} == '0'
                            ? " and "
                            : ", "
                    );
            }
        }

        $output = rtrim($output, ", ");
    }

    if ($fraction > 0)
    {
        $output .= " point";
        for ($i = 0; $i < strlen($fraction); $i++)
        {
            $output .= " " . convertDigit($fraction{$i});
        }
    }

    return $output;
}

function convertGroup($index)
{
    switch ($index)
    {
        case 11:
            return " decillion";
        case 10:
            return " nonillion";
        case 9:
            return " octillion";
        case 8:
            return " septillion";
        case 7:
            return " sextillion";
        case 6:
            return " quintrillion";
        case 5:
            return " quadrillion";
        case 4:
            return " trillion";
        case 3:
            return " billion";
        case 2:
            return " million";
        case 1:
            return " thousand";
        case 0:
            return "";
    }
}

function convertThreeDigit($digit1, $digit2, $digit3)
{
    $buffer = "";

    if ($digit1 == "0" && $digit2 == "0" && $digit3 == "0")
    {
        return "";
    }

    if ($digit1 != "0")
    {
        $buffer .= convertDigit($digit1) . " hundred";
        if ($digit2 != "0" || $digit3 != "0")
        {
            $buffer .= " and ";
        }
    }

    if ($digit2 != "0")
    {
        $buffer .= convertTwoDigit($digit2, $digit3);
    }
    else if ($digit3 != "0")
    {
        $buffer .= convertDigit($digit3);
    }

    return $buffer;
}

function convertTwoDigit($digit1, $digit2)
{
    if ($digit2 == "0")
    {
        switch ($digit1)
        {
            case "1":
                return "ten";
            case "2":
                return "twenty";
            case "3":
                return "thirty";
            case "4":
                return "forty";
            case "5":
                return "fifty";
            case "6":
                return "sixty";
            case "7":
                return "seventy";
            case "8":
                return "eighty";
            case "9":
                return "ninety";
        }
    } else if ($digit1 == "1")
    {
        switch ($digit2)
        {
            case "1":
                return "eleven";
            case "2":
                return "twelve";
            case "3":
                return "thirteen";
            case "4":
                return "fourteen";
            case "5":
                return "fifteen";
            case "6":
                return "sixteen";
            case "7":
                return "seventeen";
            case "8":
                return "eighteen";
            case "9":
                return "nineteen";
        }
    } else
    {
        $temp = convertDigit($digit2);
        switch ($digit1)
        {
            case "2":
                return "twenty-$temp";
            case "3":
                return "thirty-$temp";
            case "4":
                return "forty-$temp";
            case "5":
                return "fifty-$temp";
            case "6":
                return "sixty-$temp";
            case "7":
                return "seventy-$temp";
            case "8":
                return "eighty-$temp";
            case "9":
                return "ninety-$temp";
        }
    }
}

function convertDigit($digit)
{
    switch ($digit)
    {
        case "0":
            return "zero";
        case "1":
            return "one";
        case "2":
            return "two";
        case "3":
            return "three";
        case "4":
            return "four";
        case "5":
            return "five";
        case "6":
            return "six";
        case "7":
            return "seven";
        case "8":
            return "eight";
        case "9":
            return "nine";
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...