如何阅读值的数字写成的话吗?
-
09-06-2019 - |
题
正如我们所知道的数字可以写在数字,或者叫他们的名字。同时有很多实例中可以找到,其中123到一百二十三个,我不能找到很好的例子如何转换的另一方式。
一些注意事项:
- 红衣主教/名义或顺序:"一"和"第一"
- 共同拼写错误:"四"/"四"
- 数百/千:2100->"二十一百"并且"二千一百"
- 分离器:"十一百五十二",但也"elevenhundred fiftytwo"或"十一百五十二个"和诸如此类的东西
- 俗语:"第三十的东西"
- 部分:'三分之一','的两个五分之二的'
- 常见的名称:'一个十','一半'
并且有可能更需要注意的可能尚未列出。假设算法需要非常强大,甚至理解的拼写错误。
什么领域/文件/研究/算法应当我读了解如何编写这一切?哪里是信息?
PS:我的最后分析器实际上应该明白3种不同的语言、英语、俄语以及希伯来语。也许在稍后阶段更多语言,将增加。希伯来文的也有男性/女性的数字,比如"个人"和"一个女人"有一个不同的"一个"—"ehad"和"理".俄罗斯还有一些其自身的复杂性。
谷歌的一项伟大的工作。例如:
(反过来也是可能的 http://www.google.com/search?q=999999999999+in+english)
解决方案
我是玩弄一个挂分析程序做什么样的你想(和可后,作为一个单独的答复以后)当我注意到,有一个非常简单的算法,没有一个非常好的工作与常见的形式的数字英语、西班牙和德国,在非常少。
工作与英例如,需要一个典地图话的价值观显而易见的方式:
"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
等等。我不是说它是完美的,但对于一个快速和肮脏的它确实很好。
解决您的具体清单编辑:
- 红衣主教/名义或顺序:"一"和"第一"-- 只是把它们放在字典中
- 英文/英国:"四"/"四"-- 同上
- 数百/千:2100->"二十一百"并且"二千一百"-- 作为是
- 分离器:"十一百五十二",但也"elevenhundred fiftytwo"或"十一百五十二个"和诸如此类的东西-- 只是定义"下一个单词"是最长的前缀相匹配的一定义的字,或者到下一个非词,如果没有这样做,因为一开始
- colloqialisms:"第三十什么"-- 工作
- 片段:'三分之一','的两个五分之二的'-- 呃,还没有...
- 常见的名称:'一个十','一半'-- 工作;你甚至可以做的东西像"半打"
6号是唯一一个我没有准备好的答案,这是因为的含糊之间的序号和馏分(英文中的至少)加入事实上,我的最后一杯咖啡 很多 小时前。
其他提示
这不是一个容易的问题,我不知道图书馆做到这一点。我可能会坐下来写这样的事情一段时间。我会做它在序言中,Java或Haskell,虽然。我可以看到,有几个问题:
- 标记:有时,数字都写一千一百五十二个,但我已经看到elevenhundred fiftytwo或十一百五十二和诸如此类的东西。一个就要进行一次调查在何种形式实际上是在使用。这可能特别棘手,用希伯来语。
- 拼写错误:这不是很难.你有一个数量有限的单词,并且一点Levenshtein-distance魔法应该可以做到。
- 替代形式,就像你已经提到的,存在。这包括序号/基数,以及第四十/四十和...
- ...常见的名称或者通常使用的短语和NEs(名的实体)。你想要取30从三十年战争或2从第二次世界大战?
- 罗马数字吗?
- Colloqialisms,例如"第三十什么"和"三个欧洲和弹片",这是我不知道如何对待。
如果你有兴趣在这,我可以给它一个镜头,这个周末。我的想法可能是使用UIMA和切分,那么要进一步的标记/消除歧义和最后翻译。可能会有更多的问题,让我们来看看如果我能想出一些更有趣的事情。
对不起,这不是一个真正的答案,只是一个扩展到你的问题。我会让你知道如果我发现/写的东西。
顺便说一句,如果你有兴趣在语义的数字,我只找到一个 有趣的纸 由弗里德里克Moltmann,讨论一些问题有关的逻辑的解释数字。
我有一些代码我写了一段时间前: text2num.这种做一些你想要什么,但它不处理序号。我还没有实际使用这个代码的任何东西,所以它很大程度上未经测试的!
使用的蟒蛇 图案-en 图书馆:
>>> from pattern.en import number
>>> number('two thousand fifty and a half') => 2050.5
你应该记住,欧洲和美洲数不同。
欧洲标准:
One Thousand
One Million
One Thousand Millions (British also use Milliard)
One Billion
One Thousand Billions
One Trillion
One Thousand Trillions
在这里, 是一个小型的参考。
一个简单的方法以看到的差异如下:
(American counting Trillion) == (European counting Billion)
序号并不适用,因为他们不能参加有意义的方式与其他数语言(...至少在英文)
例如一百和第一、第二十一,等等。
然而,还有另外一个英国/美国的警告字'和'
即
一百和一(英语) 一百人(美国)
此外,使用"a"意味着一个英文
一千=一千
...在一个侧面说明谷歌的计算器没一个了不起的工作。
甚至...
...跆拳道?!? 一个分数,加上一个十几在罗马数字
这里是一个非常强大的解决方案中。
据我所知这是一个独特的执行方法。
;----------------------------------------------------------------------
; numbers.clj
; written by: Mike Mattie codermattie@gmail.com
;----------------------------------------------------------------------
(ns operator.numbers
(:use compojure.core)
(:require
[clojure.string :as string] ))
(def number-word-table {
"zero" 0
"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
"fourty" 40
"fifty" 50
"sixty" 60
"seventy" 70
"eighty" 80
"ninety" 90
})
(def multiplier-word-table {
"hundred" 100
"thousand" 1000
})
(defn sum-words-to-number [ words ]
(apply + (map (fn [ word ] (number-word-table word)) words)) )
; are you down with the sickness ?
(defn words-to-number [ words ]
(let
[ n (count words)
multipliers (filter (fn [x] (not (false? x))) (map-indexed
(fn [ i word ]
(if (contains? multiplier-word-table word)
(vector i (multiplier-word-table word))
false))
words) )
x (ref 0) ]
(loop [ indices (reverse (conj (reverse multipliers) (vector n 1)))
left 0
combine + ]
(let
[ right (first indices) ]
(dosync (alter x combine (* (if (> (- (first right) left) 0)
(sum-words-to-number (subvec words left (first right)))
1)
(second right)) ))
(when (> (count (rest indices)) 0)
(recur (rest indices) (inc (first right))
(if (= (inc (first right)) (first (second indices)))
*
+))) ) )
@x ))
这里是一些例子
(operator.numbers/words-to-number ["six" "thousand" "five" "hundred" "twenty" "two"])
(operator.numbers/words-to-number ["fifty" "seven" "hundred"])
(operator.numbers/words-to-number ["hundred"])
我LPC执行你的一些要求(美国只有英文本):
internal mapping inordinal = ([]);
internal mapping number = ([]);
#define Numbers ([\
"zero" : 0, \
"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, \
])
#define Ordinals ([\
"zeroth" : 0, \
"first" : 1, \
"second" : 2, \
"third" : 3, \
"fourth" : 4, \
"fifth" : 5, \
"sixth" : 6, \
"seventh" : 7, \
"eighth" : 8, \
"ninth" : 9, \
"tenth" : 10, \
"eleventh" : 11, \
"twelfth" : 12, \
"thirteenth" : 13, \
"fourteenth" : 14, \
"fifteenth" : 15, \
"sixteenth" : 16, \
"seventeenth" : 17, \
"eighteenth" : 18, \
"nineteenth" : 19, \
"twentieth" : 20, \
"thirtieth" : 30, \
"fortieth" : 40, \
"fiftieth" : 50, \
"sixtieth" : 60, \
"seventieth" : 70, \
"eightieth" : 80, \
"ninetieth" : 90, \
"hundredth" : 100, \
"thousandth" : 1000, \
"millionth" : 1000000, \
"billionth" : 1000000000, \
])
varargs int denumerical(string num, status ordinal) {
if(ordinal) {
if(member(inordinal, num))
return inordinal[num];
} else {
if(member(number, num))
return number[num];
}
int sign = 1;
int total = 0;
int sub = 0;
int value;
string array parts = regexplode(num, " |-");
if(sizeof(parts) >= 2 && parts[0] == "" && parts[1] == "-")
sign = -1;
for(int ix = 0, int iix = sizeof(parts); ix < iix; ix++) {
string part = parts[ix];
switch(part) {
case "negative" :
case "minus" :
sign = -1;
continue;
case "" :
continue;
}
if(ordinal && ix == iix - 1) {
if(part[0] >= '0' && part[0] <= '9' && ends_with(part, "th"))
value = to_int(part[..<3]);
else if(member(Ordinals, part))
value = Ordinals[part];
else
continue;
} else {
if(part[0] >= '0' && part[0] <= '9')
value = to_int(part);
else if(member(Numbers, part))
value = Numbers[part];
else
continue;
}
if(value < 0) {
sign = -1;
value = - value;
}
if(value < 10) {
if(sub >= 1000) {
total += sub;
sub = value;
} else {
sub += value;
}
} else if(value < 100) {
if(sub < 10) {
sub = 100 * sub + value;
} else if(sub >= 1000) {
total += sub;
sub = value;
} else {
sub *= value;
}
} else if(value < sub) {
total += sub;
sub = value;
} else if(sub == 0) {
sub = value;
} else {
sub *= value;
}
}
total += sub;
return sign * total;
}
嗯,我是太晚上对于这个问题的答案,但是我工作小测试方案,似乎已经非常好了我。我用(简单,但是丑陋的,大)经常表达找到所有的话对我来说。表达如下:
(?<Value>(?:zero)|(?:one|first)|(?:two|second)|(?:three|third)|(?:four|fourth)|
(?:five|fifth)|(?:six|sixth)|(?:seven|seventh)|(?:eight|eighth)|(?:nine|ninth)|
(?:ten|tenth)|(?:eleven|eleventh)|(?:twelve|twelfth)|(?:thirteen|thirteenth)|
(?:fourteen|fourteenth)|(?:fifteen|fifteenth)|(?:sixteen|sixteenth)|
(?:seventeen|seventeenth)|(?:eighteen|eighteenth)|(?:nineteen|nineteenth)|
(?:twenty|twentieth)|(?:thirty|thirtieth)|(?:forty|fortieth)|(?:fifty|fiftieth)|
(?:sixty|sixtieth)|(?:seventy|seventieth)|(?:eighty|eightieth)|(?:ninety|ninetieth)|
(?<Magnitude>(?:hundred|hundredth)|(?:thousand|thousandth)|(?:million|millionth)|
(?:billion|billionth)))
这里显示与行符的格式目的。。
不管怎么说,我的方法来执行这RegEx图像PCRE,然后回读的名为匹配。和它的工作在所有的不同实例,列在这个问题,减去"半数",类型,因为我没有加入他们,但你可以看到,它不会硬要这样做。这解决了很多问题。例如,地址的以下项目,在原来的问题和其他的答案:
- 红衣主教/名义或顺序:"一"和"第一"
- 共同拼写错误:"四"/"四"(请注意,它并没有明确地解决这个问题,那将是什么你想要做之前,你通过了串到这种分析器。这种分析器看到的这例如"四个一"...)
- 数百/千:2100->"二十一百"并且"二千一百"
- 分离器:"十一百五十二",但也"elevenhundred fiftytwo"或"十一百五十二个"和诸如此类的东西
- colloqialisms:"第三十事"(这也是不完全的解决,为什么是"什么"?好了,这代码中找到这些作为只是"30").**
现在,而不是储存这个怪物一定期表达您的来源,我是在考虑建立这RegEx在运行时,采用类似的如下:
char *ones[] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve",
"thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
char *tens[] = {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
char *ordinalones[] = { "", "first", "second", "third", "fourth", "fifth", "", "", "", "", "", "", "twelfth" };
char *ordinaltens[] = { "", "", "twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth", "seventieth", "eightieth", "ninetieth" };
and so on...
容易的部分在这里是我们是仅存的话这一问题。在这种情况下的第六,你会注意到,没有一个入口,因为它只是它的正常数量与日上涨了...但是那些像十二个需要不同的关注。
好了,现在我们有代码,以建立我们(丑)RegEx,现在我们只是执行它在我们的数字符串。
有一件事我会建议,是过滤器,或吃个词"和"。这是不必要的,并且只会导致其他问题。
所以,什么你想要做的就是设置一个功能,通过匹配的名为"数量级"成一个功能,看起来在所有可能的幅度值,并乘以你目前的结果,值的幅度。然后,你创建的一个函数,看起来在"价值"命名的匹配,并返回int(或者任何你都使用),基于价值的发现。
所有的价值比赛都加入到你的结果,同时magnitutde匹配结果乘以mag的价值。因此,两百五十万变得以"2",然后"2*100",然后"200+50",然后"250*1000",结束有250000...
只是为了好玩,我写了一vbScript版本的这个和它的工作很棒所有的例子。现在,它不支持名为相匹配,所以我不得不工作一点更难获得正确的结果,但我得到了它。底线是,如果它是一个"价值"相匹配,将它添加你的蓄积。如果它是一个数量级相匹配,乘你的蓄100,1000,1000000,1000000000,等等。这将为你提供一些相当令人惊异的结果,以及所有您需要做的调整对于像"半数"是把它们添加到你的RegEx,把在码标记,并处理它们。
嗯,我希望这个职位可以帮助别人在那里。如果有人想要,我可以后,通过vbScript伪的代码,我在使用的测试这个,但是,这不是漂亮的码,而不是生产的代码。
如果我可以..什么是最终的语言,这将会写在?C++,或者类似的一个脚本语言?格雷格Hewgill的来源,将很长的路要走在帮助了解如何将所有这些都在一起。
让我知道如果我可以的任何其他帮助。对不起,我只知道英国/美国,所以我不能帮助您与其他语言。
我是转换的序号版本声明从早期的现代化的书籍(例如"第2版","版quarta")到整数和所需的支持对于序号1至100英文和序号1-10在一些浪漫的语言。这里就是我想出了在蟒蛇:
def get_data_mapping():
data_mapping = {
"1st": 1,
"2nd": 2,
"3rd": 3,
"tenth": 10,
"eleventh": 11,
"twelfth": 12,
"thirteenth": 13,
"fourteenth": 14,
"fifteenth": 15,
"sixteenth": 16,
"seventeenth": 17,
"eighteenth": 18,
"nineteenth": 19,
"twentieth": 20,
"new": 2,
"newly": 2,
"nova": 2,
"nouvelle": 2,
"altera": 2,
"andere": 2,
# latin
"primus": 1,
"secunda": 2,
"tertia": 3,
"quarta": 4,
"quinta": 5,
"sexta": 6,
"septima": 7,
"octava": 8,
"nona": 9,
"decima": 10,
# italian
"primo": 1,
"secondo": 2,
"terzo": 3,
"quarto": 4,
"quinto": 5,
"sesto": 6,
"settimo": 7,
"ottavo": 8,
"nono": 9,
"decimo": 10,
# french
"premier": 1,
"deuxième": 2,
"troisième": 3,
"quatrième": 4,
"cinquième": 5,
"sixième": 6,
"septième": 7,
"huitième": 8,
"neuvième": 9,
"dixième": 10,
# spanish
"primero": 1,
"segundo": 2,
"tercero": 3,
"cuarto": 4,
"quinto": 5,
"sexto": 6,
"septimo": 7,
"octavo": 8,
"noveno": 9,
"decimo": 10
}
# create 4th, 5th, ... 20th
for i in xrange(16):
data_mapping[str(4+i) + "th"] = 4+i
# create 21st, 22nd, ... 99th
for i in xrange(79):
last_char = str(i)[-1]
if last_char == "0":
data_mapping[str(20+i) + "th"] = 20+i
elif last_char == "1":
data_mapping[str(20+i) + "st"] = 20+i
elif last_char == "2":
data_mapping[str(20+i) + "nd"] = 20+i
elif last_char == "3":
data_mapping[str(20+i) + "rd"] = 20+i
else:
data_mapping[str(20+i) + "th"] = 20+i
ordinals = [
"first", "second", "third",
"fourth", "fifth", "sixth",
"seventh", "eighth", "ninth"
]
# create first, second ... ninth
for c, i in enumerate(ordinals):
data_mapping[i] = c+1
# create twenty-first, twenty-second ... ninty-ninth
for ci, i in enumerate([
"twenty", "thirty", "forty",
"fifty", "sixty", "seventy",
"eighty", "ninety"
]):
for cj, j in enumerate(ordinals):
data_mapping[i + "-" + j] = 20 + (ci*10) + (cj+1)
data_mapping[i.replace("y", "ieth")] = 20 + (ci*10)
return data_mapping
尝试
开HTTP请求"http://www.google.com/search?q="+电话号码+"+in+小数".
分析结果对于您的号码。
高速缓存的数量/成果对于课程的请求。
一个地方开始寻找的 gnu get_date lib, ,这可以分析 关于任 英语文本的日期为时间戳。虽然不完全是你在寻找什么,其解决类似的问题可以提供许多有用的线索。