科学记数法数字的正则表达式?
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 格式是为编程语言而不是数据设计的,因此它可能支持您的输入不需要的东西。
【讨论】:
以上是关于科学记数法数字的正则表达式?的主要内容,如果未能解决你的问题,请参考以下文章