■No82952 (774RR さん) に追記 > 1.000000000000 と > 0.999999999999 と > 1.000000000001 とは違う数値になっちゃう。 1.000000000001 は、内部的には (2^0 +2^-40 +2^-44 +2^-45 +2^-48 +2^-49) 相当ですね。 「^」は、VB/VBA の冪演算子。(C# だと Math.Pow) Double バイナリを 2 進数で表記 1.000000000000 → 0 01111111111 0000000000000000000000000000000000000000000000000000 0.999999999999 → 0 01111111110 1111111111111111111111111111111111111101110011010001 1.000000000001 → 0 01111111111 0000000000000000000000000000000000000001000110011000 0.99999999999999978 → 0 01111111110 1111111111111111111111111111111111111111111111111110 0.99999999999999989 → 0 01111111110 1111111111111111111111111111111111111111111111111111 1.00000000000000000 → 0 01111111111 0000000000000000000000000000000000000000000000000000 1.00000000000000020 → 0 01111111111 0000000000000000000000000000000000000000000000000001 上記の Double バイナリを 10進小数に復元 1.000000000000 → 1.00000000000000000000000000000000000000000000000000000 0.999999999999 → 0.99999999999900002212172012150404043495655059814453125 1.000000000001 → 1.00000000000100008890058234101161360740661621093750000 0.99999999999999978 → 0.99999999999999977795539507496869191527366638183593750 0.99999999999999989 → 0.99999999999999988897769753748434595763683319091796875 1.00000000000000000 → 1.00000000000000000000000000000000000000000000000000000 1.00000000000000020 → 1.00000000000000022204460492503130808472633361816406250
自分で正規表現エンジン(という程たいそうなものではないですが)を作りつつ、 この問題を考えてみていました。 当初の興味は https://bynatures.hatenadiary.jp/entry/3317/ の方法でNGワードを長くしていくと、 正規表現はどのくらい複雑になるのか? でした。 しかし、http://www.formauri.es/personal/pgimeno/misc/non-match-regex/ を 教えてもらい、そのうち、ジェネレーターを作ることが目的になってしまいました! 楽しそうだったので。 さて、以下の二つのアプローチで正規表現を生成していました。 @ジェネレーターのサイトの出力を解析して、正規表現を出力するメソッドを作る ANGワードを与えてDFAを作り、そのDFAを正規表現に変換する @に関しては No99776 で報告しています。 Aに関してはソースコードは割愛しますが、No99777 の資料に沿って実装してみました。 No99776 と同様、正規表現を示すと以下のようになりました(先頭の5個のみ)。 Regex01: ^[^0]*$ Regex02: ^[^0]*0([^01][^0]*0|0)*([^01][^0]*)?|[^0]*$ Regex03: ^[^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|([^0]*0([^01][^0]*0|0)*([^01][^0]*)?|[^0]*)$ Regex04: ^[^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2)*(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|(([^03][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^03][^0]*)?))|([^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|([^0]*0([^01][^0]*0|0)*([^01][^0]*)?|[^0]*))$ Regex05: ^[^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2)*3(([^04][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2)*3)*(([^04][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2)*(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|(([^03][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^03][^0]*)?))|(([^04][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|(([^04][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^04][^0]*)?)))|([^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*2)*(([^03][^0]*0|0)([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|(([^03][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^03][^0]*)?))|([^0]*0([^01][^0]*0|0)*1(([^02][^0]*0|0)([^01][^0]*0|0)*1)*(([^02][^0]*0|0)([^01][^0]*0|0)*([^01][^0]*)?|([^02][^0]*)?)|([^0]*0([^01][^0]*0|0)*([^01][^0]*)?|[^0]*)))$ この調子でRegex16を書くと、UTF-8で8MBを超えるテキストになります! No99777 の資料のアルゴリズムを使うなら、できるだけ短い正規表現を作るように工夫しないとダメですね。 それか、改めて正規表現を短くするアルゴリズム(そんなのあるのか知らんけど)噛ますか。 【まとめ】 NGワードを長くすると、正規表現は長くなる! 最後に所感。 ・同じDFAでも、それと等価な正規表現はたくさんあるのかー!へぇー! ・No99777 の資料のアルゴリズムで、できるだけ短い正規表現を得るにはどうしたらいいのかな? ・DFAに最簡DFAがあるように、正規表現にも最も簡潔な正規表現が定義できて、それを得るアルゴリズムあるのかな? ・文字列の否定は正規表現で書けたけど、正規表現の否定って正規表現で書けるのかな?
- Child Tree -