好吧,我在回答这个问题时为时已晚,但我正在研究一个似乎对我来说效果很好的小测试场景。我使用了一个(简单但丑陋且大的)正则表达式来为我定位所有单词。表达式如下:
(?<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)))
此处显示用于格式化目的的换行符..
无论如何,我的方法是用 PCRE 之类的库执行这个 RegEx,然后读回命名的匹配项。它适用于这个问题中列出的所有不同示例,减去“一半”类型,因为我没有添加它们,但正如你所看到的,这样做并不难。这解决了很多问题。例如,它解决了原始问题和其他答案中的以下项目:
- 基数/名义或序数:“一”和“第一”
- 常见的拼写错误:“forty”/“fourty”(请注意,它没有明确解决这个问题,这将是您在将字符串传递给此解析器之前想要做的事情。此解析器将此示例视为“FOUR”。 ..)
- 百/千:2100 -> “2100”和“2010”
- 分隔符:“十一百五十二”,还有“十一百五十二”或“十一百五十二”等等
- 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...
这里最简单的部分是我们只存储重要的单词。在 SIXTH 的情况下,您会注意到它没有条目,因为它只是带有 TH 的普通数字......但是像 TWELVE 这样的需要不同的注意。
好的,现在我们有了构建(丑陋的)RegEx 的代码,现在我们只需在我们的数字字符串上执行它。
我会推荐的一件事是过滤或吃掉“AND”这个词。这没有必要,只会导致其他问题。
因此,您要做的是设置一个函数,将“幅度”的命名匹配传递给一个查看所有可能幅度值的函数,并将当前结果乘以该幅度值。然后,您创建一个函数来查看名为“值”的匹配项,并根据在那里发现的值返回一个 int(或您正在使用的任何内容)。
所有 VALUE 匹配都会添加到您的结果中,而 magnitutde 匹配将结果乘以 mag 值。所以,二十五万变成了“2”,然后是“2 * 100”,然后是“200 + 50”,然后是“250 * 1000”,最后是250000……
只是为了好玩,我为此编写了一个 vbScript 版本,它与提供的所有示例配合得很好。现在,它不支持命名匹配,所以我不得不更加努力地获得正确的结果,但我明白了。底线是,如果它是“价值”匹配,请将其添加到您的累加器中。如果是幅度匹配,请将您的累加器乘以 100、1000、1000000、1000000000 等...这将为您提供一些非常惊人的结果,而您所要做的调整“一半”之类的事情就是将它们相加到你的正则表达式,为它们输入一个代码标记,然后处理它们。
好吧,我希望这篇文章能帮助一些人。如果有人愿意,我可以通过我用来测试它的 vbScript 伪代码发布,但是,它不是漂亮的代码,也不是生产代码。
如果可以的话.. 这将用什么语言编写?C++,还是类似脚本语言的东西?Greg Hewgill 的消息来源将大大有助于理解所有这些是如何结合在一起的。
让我知道我是否可以提供任何其他帮助。抱歉,我只懂英语/美语,所以无法帮助您了解其他语言。