bug*_*net 42 regex parsing scientific-notation
我希望能够编写一个函数,它以科学记数法形式接收一个数字作为字符串,并将系数和指数分开作为单独的项目.我可以使用正则表达式,但传入的数字可能不会被标准化,我更愿意能够规范化然后打破这些部分.
一位同事已经使用VB6获得了解决方案的一部分,但它并不完全存在,如下面的成绩单所示.
cliVe> a = 1e6
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 10 exponent: 5
Run Code Online (Sandbox Code Playgroud)
应该是1和6
cliVe> a = 1.1e6
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.1 exponent: 6
Run Code Online (Sandbox Code Playgroud)
正确
cliVe> a = 123345.6e-7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: -2
Run Code Online (Sandbox Code Playgroud)
正确
cliVe> a = -123345.6e-7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: -2
Run Code Online (Sandbox Code Playgroud)
应该是-1.233456和-2
cliVe> a = -123345.6e+7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: 12
Run Code Online (Sandbox Code Playgroud)
正确
有任何想法吗?顺便说一句,Clive是一个基于VBScript的CLI,可以在我的博客上找到.
Jas*_*n S 75
谷歌在"科学记谱法正则表达式"中显示了一些匹配,包括这一个(不要使用!!!!)使用
*** warning: questionable ***
/[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/
Run Code Online (Sandbox Code Playgroud)
其中包括-.5e7和+ 00000e33等情况(两者都可能不允许).
相反,我强烈建议您使用Doug Crockford的JSON网站上的语法,该网站明确记录了JSON中数字的构成.这是从该页面获取的相应语法图:
alt text http://www.json.org/number.gif
如果你查看他的json2.js脚本的第456行(在javascript中安全地转换为JSON),你会看到正则表达式的这一部分:
/-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/
Run Code Online (Sandbox Code Playgroud)
具有讽刺意味的是,它与他的语法图不符....(看起来我应该提交一个bug)我相信实现该语法图的正则表达式是这样的:
/-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/
Run Code Online (Sandbox Code Playgroud)
如果你想允许一个初始+,你会得到:
/[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/
Run Code Online (Sandbox Code Playgroud)
根据自己的喜好添加捕获括号.
我还强烈建议您充实一堆测试用例,以确保包含您想要包含(或不包括)的可能性,例如:
allowed:
+3
3.2e23
-4.70e+9
-.2E-4
-7.6603
not allowed:
+0003 (leading zeros)
37.e88 (dot before the e)
Run Code Online (Sandbox Code Playgroud)
祝好运!
基于评分最高的答案,我将正则表达式稍微修改为/^[+\-]?(?=.)(?:0|[1-9]\d*)?(?:\.\d*)?(?:\d[eE][+\-]?\d+)?$/.
这样做的好处是:
.9(我用 做了(?:0|[1-9]\d*)可选?)(?=.))e9因为它需要\d在科学计数法之前我的目标是用它来捕获重要数字并进行重要数学运算。因此,我还将使用捕获组将其分割,如下所示/^[+\-]?(?=.)(0|[1-9]\d*)?(\.\d*)?(?:(\d)[eE][+\-]?\d+)?$/:
关于如何从中获取有效数字的解释:
parseFloat()undefined's 替换为'')应该给出可以从中提取有效数字的原始数字。这个正则表达式还可以防止匹配左侧填充的零,JavaScript 有时会接受这种匹配,但我发现它会导致问题,并且不会给有效数字添加任何内容,因此我认为防止左侧填充的零是一个好处(尤其是在表单中)。但是,我确信可以修改正则表达式以吞噬左侧填充的零。
我看到这个正则表达式的另一个问题是它不会匹配90.e9或其他此类数字。然而,我发现这个或类似的匹配极不可能,因为科学计数法中的惯例是避免此类数字。尽管您可以在 JavaScript 中输入它,但您也可以轻松输入9.0e10并获得相同的有效数字。
更新
在我的测试中,我还发现了它可以匹配的错误'.'。因此,应修改前瞻以(?=\.\d|\d)得出最终的正则表达式:
/^[+\-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:\d[eE][+\-]?\d+)?$/
Run Code Online (Sandbox Code Playgroud)