一尘不染

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

algorithm

众所周知,数字既可以用数字写成,也可以用名字来称呼。尽管有很多将123转换为123的示例,但我找不到如何将123转换为123的良好示例。

一些警告:

  1. 基数/标称或序数:“一个”和“第一”
  2. 常见的拼写错误:“四十” /“四十”
  3. 千/千:2100->“二十一”,还有“二十一百”
  4. 分隔符:“一百一十二点二十五”,也可以是“一百一十二点五十二”或“一百一十二点五十二”
  5. 口语:“三十多岁”
  6. 分数:“三分之一”,“五分之二”
  7. 通用名称:“十几”,“半”

而且可能还有更多未列出的警告。假设算法需要非常鲁棒,甚至可以理解拼写错误。

我应该阅读哪些领域/论文/研究/算法以学习如何编写所有这些内容?信息在哪里?

PS:我的最终解析器实际上应该理解3种不同的语言,英语,俄语和希伯来语。也许稍后会添加更多的语言。希伯来语也有男性/女性数字,例如“一个男人”和“一个女人”具有不同的“一个”,即“
ehad”和“ ahat”。俄语也有其自身的复杂性。

Google在这方面做得很好。例如:

http://www.google.com/search?q=小数点后加一千两和一加百+加+五+十二+和四+五+

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


阅读 174

收藏
2020-07-28

共1个答案

一尘不染

当我发现有一个非常简单的算法可以很好地处理英文,西班牙文和英文的常见数字形式时,我正在玩PEG解析器来做您想做的事情(并可能在以后将其作为单独的答案发布)。至少是德语。

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

"one" -> 1, "two" -> 2, ... "twenty" -> 20,
"dozen" -> 12, "score" -> 20, ...
"hundred" -> 100, "thousand" -> 1000, "million" -> 1000000

…等等

该算法只是:

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

例如,它的进度如下:

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

等等。我并不是说它是完美的,但是对于快速又肮脏的它来说效果很好。


在编辑时处理您的特定列表:

  1. 基数/标称或序数:“一个”和“第一”- 只需将它们放入字典中
  2. 英语/英语:“ fourty” /“ forty”- 同上
  3. 千/千:2100->“二十一”以及“二十一百”- 按原样工作
  4. 分隔符:“ 112”,也可以是“ 112”或“ 112 522”等( 仅将“下一个词”定义为与定义的词匹配的最长前缀,或者直到下一个)如果没有,则为非单词
  5. 口语主义:“三十年代”- 作品
  6. 片段:“三分之一”,“五分之二”- 嗯,还没有…
  7. 通用名称:“打”,“半”- 作品; 您甚至可以做“六打”之类的事情

数字6是我唯一没有答案的答案,这是因为普通和分数之间的歧义(至少用英语来说),加之我最后一杯咖啡是 很多 小时前的事实。

2020-07-28