Преобразование числа на английском языке в цифровое значение (игнорировать десятичные дроби)

Я хочу преобразовать значения этих типов: "3 миллиона", "24 тысячи", "350 тысяч" и т. Д. В число. В JavaScript(так что я могу сделать это на стороне клиента) или PHP(на стороне сервера). есть ли функция для этого? как PHP strtotime() функционировать?

input                  output
3 million              3000000
24 thousand            24000
350 thousand           350000

6 ответов

Вы хотите их объединить?

function convert(num) {

  return num.match(/(\d+)( ?\w* ?)/g).map(mapGroups)
    .reduce(function(p,c){return p+c;});

  function mapGroups(str){
    if (/million/.test(str)){
      return str.match(/\d+/)[0] * 1000000;
    }                                                                                                                                                                                                       
    if (/thousand/.test(str)){
      return str.match(/\d+/)[0] * 1000;
    }   
    if (/hundred/.test(str)){
      return str.match(/\d+/)[0] * 100;
    }   
    return +str;
  }
}

convert("3 million 240 thousand 7 hundred 54"); //3240754
convert("5 millions 7 hundreds 54"); //5000754

это очень просто, но вы получаете контроль.

Чудесного решения не существует, но PHP-функция NumberFormatter:: parse может помочь вам решить вашу проблему:

$fmt = numfmt_create('en_US', NumberFormatter::SPELLOUT);
echo numfmt_format($fmt, '1234567');

Выведет один миллион двести тридцать четыре тысячи пятьсот шестьдесят семь и

$fmt = numfmt_create('en_US', NumberFormatter::SPELLOUT);
echo numfmt_parse($fmt, 'one million two hundred thirty-four thousand five hundred sixty-seven');

Будет выводить 1234567.

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

    $str = str_replace('hundred','00',$str);
    $str = str_replace('thousand','000',$str);
    $str = str_replace('million','000000',$str);
    $str = str_replace('billion','000000000',$str);
$str = str_replace(' ','',$str);

Как это:)

Мне нравятся такие проблемы, вот мой взгляд на PHP. Я хотел сделать его максимально компактным, и его легко расширить, если вы хотите использовать thousandths или же millionths,

Я должен был добавить + 0 иметь дело с возможностью трейлинга +, который работает, но я не фанат того, как это выглядит. Если возникает необходимость отфильтровать символы до eval()Я бы ввел некоторое регулярное выражение и просто избавиться от \+$,

$find_replace = array(
    array('hundred', 'thousand', 'million', 'billion'),
    array('* 1e2 +', '* 1e3 +', '* 1e6 +', '* 1e9 +')
);

function words_to_number($input) {
    global $find_replace;
    $equation = str_replace($find_replace[0], $find_replace[1], $input) . ' + 0';
    $eval_result = eval('$result = ' . $equation . ';');
    return $eval_result === false ? $eval_result : $result;
}

$words = '3 million 240 thousand 7 hundred 54';
$number = words_to_number($words);
echo $words . ($number === false ? ' error!' : " == $number") . "\n";
// 3 million 240 thousand 7 hundred 54 == 3240754

$words = '5 thousand';
$number = words_to_number($words);
echo $words . ($number === false ? ' error!' : " == $number") . "\n";
// 5 thousand == 5000

Предполагая, что:

  1. у вас есть числовая часть ВСЕГДА написана в числовом формате
  2. единица является последовательной и правильно написана, то есть у вас всегда есть "миллион", а не "миллионы" или "милион"
  3. правильный синтаксис числа (что-то вроде 3 миллиона, 24 тысячи, ecc)

Вы можете использовать карту как:

var unitMap = [million:6, thousand:3, '':1] // add as many units as you like

а затем преобразовать строку в число. Вот идея, используя javascript и jQuery.

var UNIT_SEPARATOR = ', '; // what separates the number parts (millions from thousands, ecc)
var VALUE_UNIT_SEPARATOR = ' '; // what goes between the value and the unit
var unitMap = {
    billion:9,
    million:6,
    thousand:3,
    '':1
}; // add as many units as you like

$('#convert').click(function () {
    var number = $('#input').val();
    var numberParts = number.split(UNIT_SEPARATOR);
    var convertedNumber = 0;

    for (var i = 0; i < numberParts.length; i++) {
        var splitUnit = numberParts[i].split(' ');
        var value = parseFloat(splitUnit[0]);
        var exp = (splitUnit.length === 1) ? 0 : parseInt(unitMap[splitUnit[1]]);

        var temp = value * Math.pow(10, exp);

        convertedNumber += temp;
    }

    $('#result').text(convertedNumber);
});

Вот скрипка

ПРИМЕЧАНИЕ это подсказка. Ввод должен быть санирован и проверен перед использованием. Кроме того, этот подход очень подвержен ошибкам, поэтому вы должны тщательно проверить его перед применением (см. Вышеизложенные предположения).

Надеюсь, поможет!;)

Этот пример был написан для преобразования чисел в слова, но во многих случаях вы можете преобразовывать слова в числа - при условии, что ввод слов совпадает с тем, что будет выведено из вычисления числа в слова.

Вы можете взять то, что вы можете использовать, и отказаться от всего остального.

<!doctype html>
<html lang= "en">
<head>
<meta charset= "utf-8">
<title>Number Strings</title>
<style>
textarea{
    font-size: 1em;
    color: black;
    font-weight: 600;
    resize: both;
}
button{
    cursor: pointer;
    text-decoration: none;
    color: black;
    font-size: 1em;
    font-weight: bold;
}
button: hover, button: focus{
    color: red;
}
p{
    font-size: 1.1em;
    font-weight: 500;
    position: relative;
    margin: 1em 1ex;
}
.leftcolumnDiv{
    display: inline-block;
    position: relative;
    max-width: 60em;
    min-width: 24em;
    border: thick navy ridge;
    border-radius: 1em;
    padding: 1em;
}
#numword_div{
    color: black;
    font-weight: 600;
    font-size: 1em;
    padding: 1em;
    font-family: sans-serif;
}
#numword_div span{
    color: green;
}
</style>

<script>
// utility for display demo and object container for number/word methods

function mr(hoo){
    if(typeof hoo== 'string') hoo= document.getElementById(hoo) || '';
    return (hoo.nodeType== 1)? hoo: null;
}

var Yankee= {
    dr: function(what, pa, hoo, txt, sty){
        var tag, el, mod, ref;
        what= what.toLowerCase().split('_');
        tag= what[0], mod= what[1], ref= mr(pa);
        el= document.createElement(tag);
        if(hoo) el.id= hoo;
        if(sty) el.style.cssText= sty;
        if(ref){
            if(mod== 'b4') ref.parentNode.insertBefore(el, ref);
            else if(mod== 'bf' && ref.firstChild){
                ref.insertBefore(el, ref.firstChild);
            }
            else ref.appendChild(el);
        }
        if(txt) el.appendChild(document.createTextNode(txt));
        return el;
    },
    zap: function(who){
        who= mr(who);
        while(who.lastChild) who.removeChild(who.lastChild);
    },
    zappit:function(who){
        who= mr(who);
        who.parentNode.removeChild(who);
    }
}

/* US English words from numbers and back*/
Math.gcd= function gcd(a, b){
    if(b) return gcd(b, a%b);
    return Math.abs(a);
}
Number.fromRoman= function(s){
    s= String(s).toUpperCase();
    if(s.length>15 ||  /[^MDCLXVI]/.test(s)) return NaN;
    var L= s.length, sum= 0, i= 0, next, val, 
    R={
        M: 1000, D: 500, C: 100, L: 50, X: 10, V: 5, I: 1
    };
    while(i<L){
        val= s.charAt(i++);
        if(!R[val]) return NaN;
        val= R[val];
        next= R[(s.charAt(i) || 'N')] || 0;
        if(next>val) val*= -1;
        sum+= val;
    }
    if(sum.toRoman()== s) return sum;
    return NaN;
}
Number.prototype.toRoman= function(){
    var n= Math.floor(this), val, s= '', limit= 3999, i= 0, 
    v= [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1], 
    r= ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
    if(n<1 || n>limit) return '';
    while(i<13){
        val= v[i];
        while(n>= val){
            n-= val;
            s+= r[i];
        }
        if(n== 0) return s;
        ++i;
    }
    return '';
}

Yankee.NW={
    nameNumbers: function(str){
        var Y= Yankee.NW, nw= Y.numberWords, 
        s= (str+'').replace(/([^\d])(?=\.\d+)/g, '$1 0').trim();
        var f, w= '', x, xs, n, ns, M, 
        rx=/(-?\d+)(\.(\d+)([eE]([+-]?\d+))?)?/g, 
        rx2=/(\d+)(\.(\d+)([eE]([+-]?\d+))?)?/, 
        rq=/((\d+)? +(and +)?)?(\d+)\/(\d+)/g;
        s= s.replace(rq, function(a){
            return Y.printFraction(a);
        });
        s= s.replace(rx, function(q){
            n= +q, 
            ns= n+'';
            M= rx2.exec(ns) || [];
            w= (n<0)? 'minus ': '';
            if(M[1]) w+= nw(M[1]);
            if(M[3]){
                f= M[3].split('').map(function(itm){
                    return nw(itm);
                });
                w+= ' point '+ f.join(' ');
                if(M[5]){
                    x= +M[5];
                    xs= x<0? 'minus ': '';
                    xs+= Y.ordinal(nw(x));
                    w+= ' times ten to the '+xs;
                }
            }
            return w || q;
        });
        return s.replace(/ {2,}/g, ' ');
    },
    numberWords: function numberWords(x){
        var n= +x;
        if(isNaN(n) || n%1) return ''+x;
        n= Math.abs(n);
        var i= 0, p, prefix= [], num, rem, 
        NK= Yankee.NW.numberwords_array, 
        w= NK[0], w1= NK[1], w2= NK[2], mag= NK[3];
        while(n>99){
            x= mag[i];
            if(n>= x){
                p= Math.floor(n/x);
                n%= x;
                prefix.push(numberWords(p)+w2[i]);
            }
            ++i;
        }
        if(prefix.length){
            prefix= prefix.join(', ');
            if(n) prefix+= ' and ';
            else return prefix;
        }
        else prefix= '';
        if(n<20) num= w[n];
        else{
            num= w1[Math.floor(n/10)];
            rem= n%10;
            if(rem) num+= ' '+w[rem];
        }
        return prefix+num;
    },
    numberwords_array: [
        ['zero', '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'], 
        [' quadrillion', ' trillion', ' billion', ' million', 
        ' thousand', ' hundred'], 
        [1e15, 1e12, 1e9, 1e6, 1e3, 100]
    ], 
    ordinal: function(s){
        var ax, rx, suffix, str= ' '+s.trim();
        ax= str.lastIndexOf(' ');
        suffix= str.substring(ax).toLowerCase();
        if(str.charAt(str.length-1)== 'y'){
            return str.slice(0, -2)+'tieth';
        }
        if(ax>1) str= str.substring(0, ax);
        else str= ' ';
        switch(suffix.trim()){
            case 'one': return str+' first';
            case 'two': return str+' second';
            case 'three': return str+' third';
            case 'five': return str+' fifth';
            case 'eight': return str+' eighth';
            case 'nine': return str+' ninth';
            case 'twelve': return str+' twelfth';
            default: return str+suffix+'th';
        }
    },
    printFraction: function(s){
        var str= s.replace('and ', '').trim()
        var num, Y= Yankee.NW, RN= Y.numberWords, 
        M=/((\d+)? +)?(\d+)\/(\d+)/.exec(str);
        if(!M) return str;
        num= M[2]? RN(M[2])+' and ': '';
        num+= RN(+M[3])+'-';
        if(M[4]=== '2') num+= 'half';
        else if(M[4]=== '4') num+= 'quarter';
        else num+= Y.ordinal(RN(+M[4]));
        if(M[3]!== '1') num+= 's';
        return num;
    },
    /* words to numbers */
    fromFraction: function(str, prec){
        var rx=/(\d+)\/(\d+)/, dec= 0, I= 0, 
        M= rx.exec(str);
        if(M){
            if(M.index>0) I= parseFloat(str);
            if(M[1]) dec= M[1]/M[2];
            if(!prec) prec= str.length+1;
            if(typeof prec== 'number') dec= +(dec.toFixed(prec));
            return I+dec;
        }
        return parseFloat(str);
    },
    reDigit: function(n){
        var sub= [], tem, d= n.match(/[a-z]+/g), L= d.length-1, 
        nwords= Yankee.NW.wordnumber_keys;
        d.map(function(w, i){
            tem= nwords[w];
            if(isFinite(tem)){
                if(tem<20 || i== L) sub.push(tem+'');
                else sub.push((tem+'').charAt(0));
            }
        });
        return sub.join('');
    },
    reFraction: function(str){
        var M, w= 0, n, d, f2= 0, prec, ax;
        ax= str.lastIndexOf(' and ');
        if(ax== -1){
            ax= 0;
            w= 'zero';
        }
        else{
            w= str.substring(0, ax);
            ax+= 4;
        }
        M= str.substring(ax).split('-');
        n= M[0];
        d= M[1];
        if(n && d){
            d= Yankee.NW.wordsToNumber(d);
            n= Yankee.NW.wordsToNumber(n);
            return [w, n/d];
        }
        return [w];
    },
    wordNumber: function(str){
        var Y= Yankee.NW, n= 0, sign= 1, whole= 0, dec= 0, frac, 
        suffix= 0, exp= 1, exsign= 1, prec, pt, 
        rx1=  /(illion|thousand|hundred)/i, 
        rx2=/( +times ten to the( +minus)? +)/g, 
        rx3=/(point|times|[^a-z, ])/, 
        s= str.toLowerCase().trim().replace(/ieth?$/, 'y').replace(/(ths?|s)$/, '');
        if(s.indexOf('minus ')== 0){
            sign= -1;
            s= s.substring(5);
        }
        if(!rx3.test(s)){
            n= (!rx1.test(s))? Y.reDigit(s): Y.wordsToNumber(s);
            return n*sign;
        }
        whole= s;
        var pt= s.split('point ');
        dec= pt[1];
        if(dec){
            whole= pt[0];
            temp= rx2.exec(dec);
            if(temp!= null){
                if(temp[2]) exsign= -1;
                suffix= dec.substring(rx2.lastIndex);
                dec= dec.substring(0, temp.index);
                suffix= Y.wordsToNumber(suffix);
                exp= Math.pow(10, suffix*exsign);
            }
            dec= Y.reDigit(dec);
            prec= dec.length+1;
            dec= +('0.'+dec);
        }
        else if(whole.indexOf('-')!= -1){
            pt= Y.reFraction(whole);
            whole= pt[0];
            dec= pt[1];
        }
        n= Y.wordsToNumber(whole.replace(/ +and +/g, ' '));
        if(dec){
            n+= dec;
            if(!prec) frac= Math.min(String(n).length, 15);
            n= n.toPrecision(frac);
        }
        if(exp!== 1) return sign*((n*exp).toExponential(prec));
        return sign*n;
    },
    wordnumber_keys:{
        billion: 1e9, eigh: 8, eight: 8, eighteen: 18, eightt: 8, eighty: 80, 
        eleven: 11, fif: 5, fifteen: 15, fifty: 50, first: 1, five: 5, forty: 40, 
        four: 4, fourteen: 14, half: 2, hundred: 100, million: 1e6, nin: 9, 
        nine: 9, nineteen: 19, ninety: 90, one: 1, quadrillion: 1e15, quarter: 4, 
        second: 2, seven: 7, seventeen: 17, seventy: 70, six: 6, sixteen: 16, 
        sixty: 60, ten: 10, third: 3, thirteen: 13, thirty: 30, thousand: 1e3, 
        three: 3, trillion: 1e12, twelf: 12, twelve: 12, twenty: 20, two: 2, zero: 0
    },
    wordsToNumber: function(s){
        var w= s.toLowerCase().replace(/(thousand|[mbr]illion),?/g, '$1,');
        var n= 0, nArray= w.split(/,/), 
        sub= 0, tem, segment, 
        nwords= Yankee.NW.wordnumber_keys;
        while(nArray.length){
            sub= 0;
            segment= nArray.shift().match(/[a-z]+/g) || [];
            segment.forEach(function(w2){
                tem= nwords[w2.trim()];
                if(isFinite(tem)){
                    if(tem<100) sub+= tem;
                    else sub*= tem;
                }
            });
            n+= sub;
        }
        return n;
    },
    //demo
    display: function(skip){
        var who= mr('strum_in'), nw= Yankee.NW, 
        v= who.value.trim(), v2, n2, p, w= '';
        if(!/[a-z\d]+/i.test(v)) return;
        var didit= mr('numword_div').textContent || mr('numword_div').innerText||'';
        if(didit.indexOf(who.value+'=')== 0) return;
        if(/^[IVXLCDM]+$/.test(v)) v= Number.fromRoman(v);
        if(/^[a-z ,-]+$/i.test(v)){
            v2= nw.wordNumber(v);
        }
        else v2= nw.nameNumbers(v);
        p= Yankee.dr('p_bf', 'numword_div', '', who.value+'= ');
        Yankee.dr('span', p, '', v2, 'color:green');
        mr('numword_div').scrollTop= 0;
        mr('strum_in').focus();
    },
    sampler: function(){
        var nw= Yankee.NW, v2, v;
        Yankee.zap('numword_div');
        mr('strum_in').value= '';
        var A= ['150', '0.12', 'fourteen hundred and ninety two', '65 1/16', '65.0045', 
        'thirty three and one- third', '2012', '98.6', 'MCMLIX', '897456971.25', 
        '1 1/2', '12 3/4', '-9', '33 1/3', Math.PI, 'nine and three- quarters', 
        'seventy eight point six four','XIX',  '1.1550046210e+17', '1.222e3', 'minus two hundred', 
        '4.5e-10', '3.125e-3', '1.56760e+25'].forEach(function(sv){
            mr('strum_in').value= sv;
            nw.display();
        });
        mr('numword_div').scrollTop= 0;
        mr('strum_in').focus()
    }
}
window.onload= function(){
    mr('toWordsBtn').onclick= Yankee.NW.display;
    mr('demoWordsBtn').onclick= Yankee.NW.sampler;
    mr('clearWordsBtn').onclick= function(){
        Yankee.zap('numword_div');
        mr('strum_in').focus();
    }
}
</script>
</head>
<body>
<p class= "breadcrumbs"><a href= "../webshop.html">Home</a> </p>
<h1>Numbers to Words, Words to Numbers<br>
<span style= "font-weight: bold; color: navy; font-size:smaller">US- English version</span> </h1>
<div class= "leftcolumnDiv">
<p>Besides digits, numerical input can include a negative sign(-50), 
decimal point(.), exponential(1.15e+25) or a real number with a division slash(1/2 or 9 3/4).</p>
<p>You can also find a number value from word input, if the words are formed
as the parser expects.(Any output word strings can be used as input.)</p>
<h3 style= "margin-top: 1em;">Enter a value to convert to(or from) words</h3>
<p id= " ">Use the "Demo" button for some examples.</p>
<p>
<textarea rows= "2" cols= "40" id= "strum_in"></textarea><br>
<button id= "toWordsBtn" type= "button" style= "margin-left: 1em;">Convert</button>
<button type= "button" id= "demoWordsBtn">Demo</button>
<button id= "clearWordsBtn" type= "button">Clear</button>
</p>
<div id= "numword_div"></div>
</div>
</body>
</html>
Другие вопросы по тегам