如何从写成单词的数字中读取值?

Evg*_*eny 50 language-agnostic algorithm parsing nlp numbers

众所周知,数字可以用数字写成,也可以用它们的名字来表示.虽然有很多例子可以将123转换成123,但我找不到如何以相反的方式转换它的好例子.

一些警告:

  1. 基数/名义或序数:"一"和"第一"
  2. 常见的拼写错误:"四十"/"十四"
  3. 数百/数千:2100 - >"二十一",还有"二千一百"
  4. 分隔符:"十一二五二",还有"十一五十二"或"十一二十二"等等
  5. 口语:"三十多岁"
  6. 分数:'三分之一','五分之二'
  7. 俗名:'一打','一半'

可能还有更多可能尚未列出的警告.假设算法需要非常健壮,甚至可以理解拼写错误.

我应该阅读哪些领域/论文/研究/算法来学习如何写这些?信息在哪里?

PS:我的最终解析器应该真正理解3种不同的语言,英语,俄语和希伯来语.也许在稍后阶段会添加更多语言.希伯来语也有男/女数字,如"一个男人"和"一个女人"有不同的"一个" - "ehad"和"ahat".俄罗斯也有一些自己的复杂性.

谷歌在这方面做得很好.例如:

http://www.google.com/search?q=two+thousand+and+one+hundred+plus+five+dozen+and+four+fifths+in+decimal

(反过来也可以http://www.google.com/search?q=999999999999+in+english)

Mar*_*usQ 46

当我注意到有一个非常简单的算法可以很好地处理英语,西班牙语和英语中的常见数字形式时,我正在玩一个PEG解析器来做你想做的事情(可能会在以后单独发布).德国人,至少.

例如,使用英语,您需要一个以明显的方式将单词映射到值的字典:

"one" -> 1, "two" -> 2, ... "twenty" -> 20,
"dozen" -> 12, "score" -> 20, ...
"hundred" -> 100, "thousand" -> 1000, "million" -> 1000000
Run Code Online (Sandbox Code Playgroud)

......等等

算法只是:

total = 0
prior = null
for each word w
    v <- value(w) or next if no value defined
    prior <- case
        when prior is null:       v
        when prior > v:     prior+v
        else                prior*v
        else
    if w in {thousand,million,billion,trillion...}
        total <- total + prior
        prior <- null
total = total + prior unless prior is null
Run Code Online (Sandbox Code Playgroud)

例如,这进展如下:

total    prior      v     unconsumed string
    0      _              four score and seven 
                    4     score and seven 
    0      4              
                   20     and seven 
    0     80      
                    _     seven 
    0     80      
                    7 
    0     87      
   87

total    prior      v     unconsumed string
    0        _            two million four hundred twelve thousand eight hundred seven
                    2     million four hundred twelve thousand eight hundred seven
    0        2
                  1000000 four hundred twelve thousand eight hundred seven
2000000      _
                    4     hundred twelve thousand eight hundred seven
2000000      4
                    100   twelve thousand eight hundred seven
2000000    400
                    12    thousand eight hundred seven
2000000    412
                    1000  eight hundred seven
2000000  412000
                    1000  eight hundred seven
2412000     _
                      8   hundred seven
2412000     8
                     100  seven
2412000   800
                     7
2412000   807
2412807
Run Code Online (Sandbox Code Playgroud)

等等.我并不是说这是完美的,但是对于快速而肮脏的事情来说它确实很好.


在编辑时解决您的特定列表:

  1. 基数/名义或序数:"一"和"第一" - 只需将它们放入字典中
  2. 英语/英语:"fourty"/"forty" - 同上
  3. 数百/数千:2100 - >"二十一",还有"二千一百" - 按原样工作
  4. 分隔符:"十一二百二十二",还有"十一五十二"或"十一二百五十二"等等 - 只是将"下一个单词"定义为匹配定义单词的最长前缀,或者直到下一个单词如果没有,那就是非单词,一开始
  5. colloqialisms:"三十多岁" - 作品
  6. 碎片:"三分之一","五分之二" - 呃,还没......
  7. 俗名:'打打','半' - 作品; 你甚至可以做"半打"之类的事情

6号是唯一一个我没有准备好答案的人,这是因为序数和分数之间的模糊性(至少在英语中)增加了我的最后一杯咖啡在几个小时前的事实.


Gre*_*ill 11

我有一些我刚才写的代码:text2num.这可以做你想要的一些,除了它不处理序数.我实际上并没有使用这个代码,所以它基本上没有经过测试!


Ale*_*rov 11

这不是一个容易的问题,我知道没有图书馆可以做到这一点.我可能会坐下来尝试写一些这样的东西.不过,我会在Prolog,Java或Haskell中做到这一点.据我所知,有几个问题:

  • 令牌化:有时,数字写成1125,但我已经看过十一五十二或十一点五十二等等.人们必须对实际使用的形式进行调查.这对希伯来语来说可能特别棘手.
  • 拼写错误:这不是那么难.你的单词数量有限,而Levenshtein距离魔法应该可以做到这一点.
  • 存在替代形式,如您已经提到的那样.这包括序数/基数,以及四十四十和......
  • ...通用名称或常用短语和NE(命名实体).你想从三十年战争中抽取30或从第二次世界大战中抽取2吗?
  • 罗马数字呢?
  • 口语,如"三十多岁"和"三欧元和弹片",我不知道该如何对待.

如果你对此感兴趣,我可以在本周末试一试.我的想法可能是使用UIMA并使用它进行标记,然后继续进行标记化/消除歧义并最终翻译.可能会有更多问题,让我们看看我是否可以提出一些更有趣的事情.

对不起,这还不是一个真正的答案,只是你问题的扩展.如果我发现/写东西,我会告诉你的.

顺便说一句,如果你对数字的语义感兴趣,我刚刚发现了Friederike Moltmann的一篇有趣的论文,讨论了有关数字逻辑解释的一些问题.


Ale*_*oks 7

使用Python pattern-en库:

>>> from pattern.en import number
>>> number('two thousand fifty and a half') => 2050.5
Run Code Online (Sandbox Code Playgroud)

  • @EricJ。标记为 [tag:language-agnostic] 的问题实际上意味着“任何编程语言都适合作为答案”(如果它回答了问题)。它并不意味着“请不要编程语言”。 (2认同)

fms*_*msf 5

你应该记住,欧洲和美国的数量不同.

欧洲标准:

One Thousand
One Million
One Thousand Millions (British also use Milliard)
One Billion
One Thousand Billions
One Trillion
One Thousand Trillions
Run Code Online (Sandbox Code Playgroud)

是一个小参考.


查看差异的简单方法如下:

(American counting Trillion) == (European counting Billion)
Run Code Online (Sandbox Code Playgroud)

  • 我以为我会指出英国不使用Milliard,而是法国人.除了复数以外,我们(英国)也没有复数百万,十亿等."有数百万的战士!" (2认同)