科学记数法数字的正则表达式?

Posted

技术标签:

【中文标题】科学记数法数字的正则表达式?【英文标题】:Regex for numbers on scientific notation? 【发布时间】:2010-12-18 18:27:51 【问题描述】:

我正在加载一个 .obj 文件,其中包含类似的行

vn 8.67548e-017 1 -1.55211e-016

用于顶点法线。我怎样才能检测到它们并将它们带入双重符号?

【问题讨论】:

【参考方案1】:

一个运行良好的正则表达式是:

-?[\d.]+(?:e-?\d+)?

转换为数字可以这样完成:String in scientific notation C++ to double conversion,我猜。

正则表达式是

-?      # an optional -
[\d.]+  # a series of digits or dots (see *1)
(?:     # start non capturing group
  e     # "e"
  -?    # an optional -
  \d+   # digits
)?      # end non-capturing group, make optional

**1) 这不是 100% 正确的,从技术上讲,只能有一个点,而在它之前只有一个(或没有)数字。但实际上,这不应该发生。所以正则表达式是一个很好的近似值,误报应该是非常不可能的。随意使正则表达式更具体。*

【讨论】:

我建议将[\d.]+ 拆分为\d+\.\d+ 以防止错误匹配。如果您不需要小数点前后的数字,请使用\d* 不匹配 5.5.5.5.5.5.5.5.5.5.5.5.5 @Martin:是的。问题是:这样的价值可能发生吗?如果是,正则表达式可以很容易地变得更具体。我的猜测是5.5.5.5 在这些情况下不太可能发生。 (我知道这是一个非常古老的评论,但尽管如此)您是否有任何理由不选择更有效的选项,因为实施起来相当简单?我无法想象它会对性能造成很大影响,而且会更可靠......? 这里甚至不考虑性能。为有效数据不会发生的情况准备正则表达式根本没有意义。无论如何,人们无法预料到每种形式的无效数据,因此“仅仅因为”使正则表达式更复杂是浪费时间。如果 5.5.5.5.5.5 预计会在输入中发生(或者如果它让您感觉更好),请务必调整正则表达式。 ;)【参考方案2】:

我尝试了许多其他解决方案都无济于事,所以我想出了这个。

       ^(-?\d+)\.?\d+(e-|e\+|e|\d+)\d+$

Debuggex Demo

任何匹配的都被认为是有效的科学记数法。

请注意:这接受e+e-e;如果您不想接受e,请使用:^(-?\d+)\.?\d+(e-|e\+|\d+)\d+$

我不确定它是否适用于 c++,但在 c# 中,您可以在正则表达式中的 ^(- 之间添加 (?i),以切换内联不区分大小写。没有它,像1.05E+10 这样声明的指数将无法被识别。

编辑:我以前的正则表达式有点错误,所以我用上面的那个替换了它。

【讨论】:

我调整了这个答案并提出了^(?:-?\d*)\.?\d+[eE][-\+]?\d+$——允许像.1e5这样在JS中有效的情况 你为什么用\d+结束第二个捕获组?它使您的正则表达式捕获非科学符号数字,例如3.1415【参考方案3】:

您可以使用:-?\d*\.?\d+e[+-]?\d+ regex 来识别科学值。

【讨论】:

永远不要使用0,1——改用?。前者较长,不清晰,效果相同。 0,1 可以替换为?。但是为什么你希望小数点是可选的呢?这不允许负数。它还错误地匹配 .0,这可能是不希望的。 @marcog:可能是因为根据示例数据,小数点是可选的。第三个字段只是“1”。【参考方案4】:

standard library function strtod 可以很好地处理指数分量(atof 也是如此,但strtod 允许您区分解析失败和解析值为零)。

【讨论】:

【参考方案5】:

如果您可以确定双精度的格式是科学的,您可以尝试以下方法:

  string inp("8.67548e-017");
  istringstream str(inp);
  double v;
  str >> scientific >> v;
  cout << "v: " << v << endl;

如果您想检测是否存在该格式的浮点数,那么上面的正则表达式就可以了。

编辑:scientific 操纵器实际上是不需要的,当您以双精度流式传输时,它会自动为您处理(无论是固定的还是科学的)

【讨论】:

我认为这是 C++ 的发展方向。摆弄有时有效但有时不适合我的正则表达式。相反,这会将粗糙的部分委托给 stl 的字符串流。这是检查有效科学格式的高级版本。【参考方案6】:

嗯,这不是您所要求的,因为它不是 Perl (gak),它是一个正则定义而不是正则表达式,但它是我用来识别 C 浮点文字扩展的东西(扩展是允许在数字字符串中使用“_”),如果您愿意,我相信您可以将其转换为不可读的正则表达式:

/* floats: Follows ISO C89, except that we allow underscores */
let decimal_string = digit (underscore? digit) *
let hexadecimal_string = hexdigit (underscore? hexdigit) *

let decimal_fractional_constant =
  decimal_string '.' decimal_string?
  | '.' decimal_string

let hexadecimal_fractional_constant =
  ("0x" |"0X")
  (hexadecimal_string '.' hexadecimal_string?
  | '.' hexadecimal_string)

let decimal_exponent = ('E'|'e') ('+'|'-')? decimal_string
let binary_exponent = ('P'|'p') ('+'|'-')? decimal_string

let floating_suffix = 'L' | 'l' | 'F' | 'f' | 'D' | 'd'
let floating_literal =
  (
    decimal_fractional_constant decimal_exponent? |
    hexadecimal_fractional_constant binary_exponent?
  )
  floating_suffix?

C 格式是为编程语言而不是数据设计的,因此它可能支持您的输入不需要的东西。

【讨论】:

以上是关于科学记数法数字的正则表达式?的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式去除除科学记数法之外的所有非数字字符

将两个正则表达式合并为一个

js 正则表达式:密码必须由6-12位数字加字母组成

Python正则表达式 | 如何只提取中文英文字母数字(含科学计数法)

正则表达式:检测密码由6-20字母和数字组成

如何修复正则表达式[重复]