科学表記法を賢明に解析しますか?
-
10-07-2019 - |
質問
科学表記法の数字を文字列として受け取り、その中から係数と指数を別々の項目として分割する関数を作成できるようにしたいのです。正規表現を使用することもできますが、着信番号は正規化されない可能性があるため、正規化してから部品を分割できるようにしたいと思います。
同僚がVB6を使用したソリューションの一部を手に入れましたが、下のトランスクリプトが示すように、まだ完全ではありません。
cliVe> a = 1e6
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 10 exponent: 5
1と6でなければなりませんでした
cliVe> a = 1.1e6
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.1 exponent: 6
正しい
cliVe> a = 123345.6e-7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: -2
正しい
cliVe> a = -123345.6e-7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: -2
-1.233456および-2
である必要がありますcliVe> a = -123345.6e+7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: 12
正しい
アイデアはありますか?ちなみに、CliveはVBScriptベースのCLIであり、私のウェブログで見つけることができます。
解決
Googleの"科学表記法regexp" には数字が表示されますこれ(使用しないでください!!! !)使用する
*** warning: questionable ***
/[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/
-。5e7や+ 00000e33などのケースが含まれます(どちらも許可しない場合があります)。
代わりに、Doug Crockfordの JSON Webサイトの構文を使用することを強くお勧めします数値を構成するものをJSONで明示的に文書化します。そのページから取った対応する構文図は次のとおりです。
(ソース: json.org )
彼の json2.js スクリプト(JavaScriptでのJSONとの安全な変換)、正規表現の次の部分が表示されます:
/-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/
皮肉なことに、彼の構文図とは一致しません....(バグを報告する必要があるようです)その構文図を実装する正規表現は次のとおりです:
/-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/
また、最初の+も許可したい場合は、次のようになります:
/[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/
キャプチャ括弧を好みに追加します。
また、次のような、含める(または含めない)可能性を含めるために、多数のテストケースを具体化することを強くお勧めします。
allowed:
+3
3.2e23
-4.70e+9
-.2E-4
-7.6603
not allowed:
+0003 (leading zeros)
37.e88 (dot before the e)
がんばって!
他のヒント
最高評価の回答を基にして、正規表現を / ^ [+ \-]?(?=。)(?: 0 | [1-9] \ d *)?( ?:\。\ d *)?(?:\ d [eE] [+ \-]?\ d +)?$ /
。
これが提供する利点は次のとおりです。
-
.9
のような一致する番号を許可します((?: 0 | [1-9] \ d *)
を?
) - 先頭の演算子のみとの一致を防ぎ、長さゼロの文字列との一致を防ぎます(lookahead、
(?=。)
を使用) - 科学表記法の前に
\ d
を必要とするため、e9
の一致を防ぎます
これにおける私の目標は、重要な数字をキャプチャし、重要な数学を行うためにそれを使用することです。したがって、次のようにグループをキャプチャしてスライスします: / ^ [+ \-]?(?=。)(0 | [1-9] \ d *)?(\。\ d *)?(?:(\ d)[eE] [+ \-]?\ d +)?$ /
。
これから重要な数字を取得する方法の説明:
- キャプチャ全体は、
parseFloat()
に渡すことができる番号です
- マッチ1〜3は未定義または文字列として表示されるため、それらを組み合わせる(
undefined
を''
に置き換える)と、有効数字の元の番号が得られます。抽出できます。
この正規表現は、JavaScriptでも受け入れられるが、原因の問題が発生し、重要な数字に何も追加されない左詰めゼロのマッチングを防止します。ただし、正規表現は、左詰めのゼロを飲み込むように変更できると確信しています。
この正規表現で見られる別の問題は、 90.e9
やその他の数値と一致しないことです。ただし、このような数字を避けることは科学表記法の慣習であるため、これまたは類似の一致は非常にまれです。 JavaScriptで入力できますが、 9.0e10
を簡単に入力して同じ有効数字を達成できます。
更新
テストでは、 '。'
と一致する可能性があるというエラーもキャッチしました。そのため、先読みは(?= \。\ d | \ d)
に変更する必要があります。これにより、最終的な正規表現が得られます。
/^[+\-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:\d[eE][+\-]?\d+)?$/
これは、すぐにハッキングしたPerlコードです。
my($sign,$coeffl,$coeffr,$exp) = $str =~ /^\s*([-+])?(\d+)(\.\d*)?e([-+]?\d+)\s*$/;
my $shift = length $coeffl;
$shift = 0 if $shift == 1;
my $coeff =
substr( $coeffl, 0, 1 );
if( $shift || $coeffr ){
$coeff .=
'.'.
substr( $coeffl, 1 );
}
$coeff .= substr( $coeffr, 1 ) if $coeffr;
$coeff = $sign . $coeff if $sign;
$exp += $shift;
say "coeff: $coeff exponent: $exp";