さて、私はこの質問の答えに遅すぎましたが、私は私にとって非常にうまくいったように見える小さなテストシナリオを働いていました。(単純ですが、醜く、大きい)正規表現を使用して、すべての単語を検索しました。式は次のとおりです。
(?<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のようなライブラリでこの正規表現を実行してから、名前付きの一致を読み戻すことでした。そして、私が追加しなかったので、「半分」のタイプを除いて、この質問にリストされたさまざまな例のすべてで機能しましたが、ご覧のとおり、そうするのは難しいことではありません。これは多くの問題に対処します。たとえば、元の質問とその他の回答の次の項目に対応しています。
- 枢機卿/名目または序数:「1つ」および「最初」
- よくあるスペルミス:「40」/「40」(これは明示的に対処されていないことに注意してください。これは、文字列をこのパーサーに渡す前に実行したいことです。このパーサーは、この例を「FOUR」と見なします。 ..)
- 数百/千:2100->「二十百」そして「二千百」
- 区切り文字:「1125」だけでなく、「1125」または「1125」など
- コロキアリズム:「30-何か」(これも「何か」とは何かとして、完全には扱われていませんか?まあ、このコードはこの数字を単に「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のようなものは別の注意が必要です。
これで、(醜い)正規表現を作成するためのコードができました。これで、数値文字列に対して実行するだけです。
私がお勧めすることの1つは、「AND」という単語をフィルタリングまたは食べることです。それは必要ではなく、他の問題につながるだけです。
したがって、実行したいのは、「マグニチュード」の名前付き一致をすべての可能なマグニチュード値を調べる関数に渡し、現在の結果にそのマグニチュードの値を乗算する関数を設定することです。次に、matchesという名前の「Value」を調べ、そこで検出された値に基づいてint(または使用しているもの)を返す関数を作成します。
すべてのVALUEの一致が結果に追加され、magnitutdeの一致は結果にmag値を掛けます。つまり、25万は「2」、「2 * 100」、「200 + 50」、「250 * 1000」の順になり、250000になります。
楽しみのために、私はこれのvbScriptバージョンを作成しましたが、提供されているすべての例でうまく機能しました。現在、名前付き一致はサポートされていないため、正しい結果を得るにはもう少し努力する必要がありましたが、うまくいきました。結論として、「VALUE」が一致する場合は、アキュムレータを追加します。マグニチュードが一致する場合は、アキュムレータに100、1000、1000000、1000000000などを掛けます。これにより、かなり驚くべき結果が得られます。「半分」などを調整するために必要なのは、それらを追加することだけです。あなたの正規表現に、それらのコードマーカーを入れて、それらを処理します。
さて、この投稿が誰かに役立つことを願っています。誰かが望むなら、私がこれをテストするために使用したvbScript擬似コードで投稿することができますが、それはきれいなコードではなく、本番コードでもありません。
可能であれば..これが書かれる最終的な言語は何ですか?C ++、またはスクリプト言語のようなもの?Greg Hewgillの情報源は、これらすべてがどのように組み合わされるかを理解するのに大いに役立ちます。
他にご不明な点がありましたらお知らせください。申し訳ありませんが、私は英語/アメリカ人しか知らないので、他の言語についてはお手伝いできません。