为了账号安全,请及时绑定邮箱和手机立即绑定

明智地解析科学记数法?

明智地解析科学记数法?

胡子哥哥 2019-08-13 15:00:08
明智地解析科学记数法?我希望能够编写一个函数,它以科学记数法形式接收一个数字作为字符串,并将系数和指数分开作为单独的项目。我可以使用正则表达式,但传入的数字可能不会被标准化,我更愿意能够规范化然后打破这些部分。一位同事已经使用VB6获得了解决方案的一部分,但它并不完全存在,如下面的成绩单所示。cliVe> a = 1e6cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)coeff: 10 exponent: 5应该是1和6cliVe> a = 1.1e6cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)coeff: 1.1 exponent: 6正确cliVe> a = 123345.6e-7cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)coeff: 1.233456 exponent: -2正确cliVe> a = -123345.6e-7cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)coeff: 1.233456 exponent: -2应该是-1.233456和-2cliVe> a = -123345.6e+7cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)coeff: 1.233456 exponent: 12正确有任何想法吗?顺便说一句,Clive是一个基于VBScript的CLI,可以在我的博客上找到。
查看完整描述

3 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞


谷歌在“科学记谱法regexp”上展示了一些比赛,包括这一场比赛(不要用它!!!!)


*** warning: questionable ***

/[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/

其中包括-.5e7和+ 00000e33等情况(您可能不希望这两种情况)。


相反,我强烈建议您使用Doug Crockford的JSON网站上的语法,该网站明确记录了JSON中数字的构成。这是从该页面获取的相应语法图:


如果你查看他的json2.js脚本的第456行(在javascript中安全地转换为JSON),你会看到正则表达式的这一部分:


/-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/

具有讽刺意味的是,它与他的语法图不符....(看起来我应该提交一个bug)我相信实现该语法图的正则表达式是这样的:


/-?(?: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)

祝好运!


查看完整回答
反对 回复 2019-08-13
?
慕仙森

TA贡献1827条经验 获得超7个赞

建立最高评级的答案,我稍微修改了正则表达式/^[+\-]?(?=.)(?:0|[1-9]\d*)?(?:\.\d*)?(?:\d[eE][+\-]?\d+)?$/

它提供的好处是:

  1. 允许匹配数字.9(我做了(?:0|[1-9]\d*)可选项?

  2. 防止在开始时仅匹配运算符并防止匹配的零长度字符串(使用前瞻性(?=.)

  3. 防止匹配e9因为它需要\d在科学记数法之前

我的目标是用它来捕获重要的数字并进行重要的数学运算。因此,我也会将捕捉组切成这样:/^[+\-]?(?=.)(0|[1-9]\d*)?(\.\d*)?(?:(\d)[eE][+\-]?\d+)?$/

解释如何从中获得重要数据:

  1. 整个捕获是您可以交付的数字 parseFloat()

  2. 匹配1-3将显示为未定义或字符串,因此组合它们(替换为undefined'')应该给出可从中提取有效数字的原始数字。

这个正则表达式还可以防止匹配左边填充的零,JavaScript有时会接受,但我看到它会导致问题并且不会对有效数字产生任何影响,所以我看到防止左边填充的零作为一个好处(特别是在表单中)。但是,我确信可以修改正则表达式以吞噬左边填充的零。

我看到这个正则表达式的另一个问题是它不匹配90.e9或其他这样的数字。但是,我发现这种或类似的匹配极不可能,因为科学记数法中的惯例是避免这样的数字。虽然您可以在JavaScript中输入它,但您可以轻松输入9.0e10并获得相同的重要数字。

UPDATE

在我的测试中,我也发现了它可以匹配的错误'.'。因此,应该修改前瞻,(?=\.\d|\d)以导致最终的正则表达式:

/^[+\-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:\d[eE][+\-]?\d+)?$/


查看完整回答
反对 回复 2019-08-13
?
绝地无双

TA贡献1946条经验 获得超4个赞

这是我刚刚快速入侵的一些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";


查看完整回答
反对 回复 2019-08-13
  • 3 回答
  • 0 关注
  • 483 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信