将单词转换为PHP中的数字

我正在试图将数字值写成整数。 例如,“iPhone拥有二十三万七百八十三个应用程序”将成为“iPhone作为230783应用程序”

在我开始编码之前,我想知道是否有任何函数/代码存在此转换。

有很多页面讨论从数字到单词的转换。 没有太多的相反的方向。 我能find的最好的是Ask Yahoo上的一些伪代码。 请参阅http://answers.yahoo.com/question/index?qid=20090216103754AAONnDz,获得一个很好的algorithm:;

那么,总的来说,你正在做两件事:find令牌(转化为数字的词)和应用语法。 简而言之,您正在为一种非常有限的语言构buildparsing器。

你需要的令牌是:

权力:一千万,十亿
一百:
十:二十,三十,九十
单位:一,二,三,九,
特别:十,十一,十二,…十九

(放弃任何“和”,因为它们是没有意义的)把连字符分成两个标记,即65个应该被处理成“六十五”

一旦你已经标记了你的string,从右移动到左。

  1. 从右边抓取所有的标记,直到你打到POWER或者整个string。

  2. parsing这些模式的停止点之后的令牌:

    特别

    单元
    十个单位
    单位百万
    单位一百特别
    单位百万
    单位一百个单位
    单位百万单位

    (这个假设在这个语法中不允许“一千七百”)

    这给你你的号码的最后三位数字。

  3. 如果你停在整个弦上,你就完成了。

  4. 如果停在电源位置,则从步骤1重新开始,直至达到更高的功率或整个弦。

老问题,但对于任何人遇到这个问题,我必须写一个解决scheme,今天。 下面对约翰·库格曼(John Kugelman)所描述的algorithm采取了与之类似的方法,但并不适用于严格的语法; 这样会允许一些怪异的命令,例如“十万一百万”仍然会产生“十万一十万”(1,100,000)。 无效位(例如拼写错误的数字)将被忽略,因此将无效string的输出视为未定义。

在user132513对joebert的回答发表评论之后,我使用了Pear's Number_Words来生成testing序列。 以下代码在0到5,000,000之间的数字上得分为100%,然后在0到10,000,000之间的100,000个数字的随机样本上得分为100%(需要花费很长时间才能运行整个100亿系列)。

/** * Convert a string such as "one hundred thousand" to 100000.00. * * @param string $data The numeric string. * * @return float or false on error */ function wordsToNumber($data) { // Replace all number words with an equivalent numeric value $data = strtr( $data, array( 'zero' => '0', 'a' => '1', 'one' => '1', 'two' => '2', 'three' => '3', 'four' => '4', 'five' => '5', 'six' => '6', 'seven' => '7', 'eight' => '8', 'nine' => '9', 'ten' => '10', 'eleven' => '11', 'twelve' => '12', 'thirteen' => '13', 'fourteen' => '14', 'fifteen' => '15', 'sixteen' => '16', 'seventeen' => '17', 'eighteen' => '18', 'nineteen' => '19', 'twenty' => '20', 'thirty' => '30', 'forty' => '40', 'fourty' => '40', // common misspelling 'fifty' => '50', 'sixty' => '60', 'seventy' => '70', 'eighty' => '80', 'ninety' => '90', 'hundred' => '100', 'thousand' => '1000', 'million' => '1000000', 'billion' => '1000000000', 'and' => '', ) ); // Coerce all tokens to numbers $parts = array_map( function ($val) { return floatval($val); }, preg_split('/[\s-]+/', $data) ); $stack = new SplStack; // Current work stack $sum = 0; // Running total $last = null; foreach ($parts as $part) { if (!$stack->isEmpty()) { // We're part way through a phrase if ($stack->top() > $part) { // Decreasing step, eg from hundreds to ones if ($last >= 1000) { // If we drop from more than 1000 then we've finished the phrase $sum += $stack->pop(); // This is the first element of a new phrase $stack->push($part); } else { // Drop down from less than 1000, just addition // eg "seventy one" -> "70 1" -> "70 + 1" $stack->push($stack->pop() + $part); } } else { // Increasing step, eg ones to hundreds $stack->push($stack->pop() * $part); } } else { // This is the first element of a new phrase $stack->push($part); } // Store the last processed part $last = $part; } return $sum + $stack->pop(); } 

我还没有对此进行太多的testing,我或多或less的只是在看到我期望的结果,但似乎是有效的,并且从左到右进行parsing。

 <?php $str = 'twelve billion people know iPhone has two hundred and thirty thousand, seven hundred and eighty-three apps as well as over one million units sold'; function strlen_sort($a, $b) { if(strlen($a) > strlen($b)) { return -1; } else if(strlen($a) < strlen($b)) { return 1; } return 0; } $keys = array( 'one' => '1', 'two' => '2', 'three' => '3', 'four' => '4', 'five' => '5', 'six' => '6', 'seven' => '7', 'eight' => '8', 'nine' => '9', 'ten' => '10', 'eleven' => '11', 'twelve' => '12', 'thirteen' => '13', 'fourteen' => '14', 'fifteen' => '15', 'sixteen' => '16', 'seventeen' => '17', 'eighteen' => '18', 'nineteen' => '19', 'twenty' => '20', 'thirty' => '30', 'forty' => '40', 'fifty' => '50', 'sixty' => '60', 'seventy' => '70', 'eighty' => '80', 'ninety' => '90', 'hundred' => '100', 'thousand' => '1000', 'million' => '1000000', 'billion' => '1000000000' ); preg_match_all('#((?:^|and|,| |-)*(\b' . implode('\b|\b', array_keys($keys)) . '\b))+#i', $str, $tokens); //print_r($tokens); exit; $tokens = $tokens[0]; usort($tokens, 'strlen_sort'); foreach($tokens as $token) { $token = trim(strtolower($token)); preg_match_all('#(?:(?:and|,| |-)*\b' . implode('\b|\b', array_keys($keys)) . '\b)+#', $token, $words); $words = $words[0]; //print_r($words); $num = '0'; $total = 0; foreach($words as $word) { $word = trim($word); $val = $keys[$word]; //echo "$val\n"; if(bccomp($val, 100) == -1) { $num = bcadd($num, $val); continue; } else if(bccomp($val, 100) == 0) { $num = bcmul($num, $val); continue; } $num = bcmul($num, $val); $total = bcadd($total, $num); $num = '0'; } $total = bcadd($total, $num); echo "$total:$token\n"; $str = preg_replace("#\b$token\b#i", number_format($total), $str); } echo "\n$str\n"; ?> 

PEAR Numbers_Words包可能是一个很好的开始: http : Numbers_Words package= Numbers_Words

你提到了一些错误脚本,请在开发者的angular度检查一下,例如:83139,如果你用口头问,它会给出不同的答案

通过一个string波纹pipe提到,并检查所有:

“巴士站号码十三十三千一百三十九”