在PHP中将单词转换为数字

use*_*513 20 php numbers cpu-word

我试图将写成单词的数值转换为整数.例如,"iPhone有二十三万七千八百三个应用程序"将成为"iPhone为230783应用程序"

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

Joh*_*ica 22

有很多页面讨论从数字到单词的转换.反方向并没有那么多.我能找到的最好的是Ask Yahoo上的一些伪代码.有关一个不错的算法,请参见http://answers.yahoo.com/question/index?qid=20090216103754AAONnDz:

好吧,总的来说,你做了两件事:找到令牌(翻译成数字的单词)和应用语法.简而言之,您正在为非常有限的语言构建解析器.

您需要的令牌是:

力量:千万,百万,百万
:百
:十,二十,三十......九十
单元:一,二,三,......九,
特别:十,十一,十二,......十九

(删除任何"和",因为它们毫无意义.将连字符分成两个标记.这是六十五个应该被处理为"六十""五")

一旦你对你的字符串进行了标记,就从右移到左边.

  1. 从右边抓住所有的标记,直到你击中POWER或整个弦.

  2. 在这些模式的停止点之后解析标记:

    SPECIAL
    TEN
    UNIT
    十个单位
    UNIT一百
    UNIT一百特殊
    UNIT百个十个
    单位一百UNIT
    UNIT百十个单位

    (这假定在这个语法中不允许"一千七百")

    这将为您提供数字的最后三位数字.

  3. 如果你停在整个字符串,你就完成了.

  4. 如果您停在电源上,请在步骤1重新开始,直到达到更高的POWER或整个琴弦.


El *_*obo 21

老问题,但是对于遇到这个问题的其他人来说,我今天必须写出一个解决方案.以下采用与John Kugelman描述的算法模糊相似的方法,但不适用于严格的语法; 因此,它将允许一些奇怪的排序,例如"十万和一百万"仍将产生相同的"一百万十万"(1,100,000).无效位(例如拼写错误的数字)将被忽略,因此将无效字符串的输出视为未定义.

根据user132513对joebert答案的评论,我使用了Pear的Number_Words来生成测试系列.以下代码在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, e.g. 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
                    // e.g. "seventy one" -> "70 1" -> "70 + 1"
                    $stack->push($stack->pop() + $part);
                }
            } else {
                // Increasing step, e.g 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();
}
Run Code Online (Sandbox Code Playgroud)