java中带有结尾的垃圾的稀疏浮动

问题描述 投票:3回答:1

背景:我正在尝试逐步解析诸如“ cos(1.2)”之类的表达式。现在,到实际的问题(注意:实际的问题主要在下一段中;其余是关于似乎几乎可行的解决方案的讨论):

假设我在Java中有一个String,它可能以浮点数开头,然后在其后有更多的“填充”。例如,我可能有52hi(以“ 52”开头,以“ hi”结尾)或-1.2e1e9(以“ -1.2e1”开头,也称为“负十二”,以“ e9”结尾) )。我想将此数字解析为双精度。

使用Double.parseDouble是很诱人的方法,但是此方法期望整个字符串为有效数字,如果不是,则引发异常。显而易见的事情是编写一个正则表达式以将数字与其他东西分开,然后使用parseDouble。

如果我正在解析整数,那还不错,就像-?[0-9]+。 (即使那样,也很容易忘记边缘情况,现在您的用户不能输入-9以表示与-9对称。因此前面的正则表达式应该为[-+]?[0-9]+。)也许是这样的(忽略大多数正则表达式默认情况下默认都不使用“。”的事实):

[-+]?[0-9]*.?[0-9]*(e[-+]?[0-9]+)?

[我们只是说空字符串是有效数字。 “ .e2”也是如此。所以可能有点复杂。或者也许我可以有一个像上面这样的“草率”正则表达式,它允许一些非数字,只要它不禁止任何实际数字即可。但是到了某个时候,我开始对自己思考:“这不应该是parseDouble的工作吗?”。它正在完成查找数字在字符串中何处结束以及其他内容开始的大部分工作,因为否则它将无法引发异常。为什么我也必须这样做?

因此,我开始寻找Java标准库中是否还有其他可以帮助您的东西。我通常选择的工具是java.util.Scanner,它具有一个不错的nextDouble()方法。但是Scanner可以处理“令牌”,因此nextDouble的真正含义是“获取下一个令牌并尝试将其解析为双精度”。标记由定界符分隔,我的默认设置是空格。因此Scanner使用“ 52 hi”不会有任何问题,但不能使用“ 52hi”。从理论上讲,定界符可以是我选择的任何正则表达式,因此我要做的就是编写一个正则表达式,当它匹配时,表示数字的结尾。但这似乎比直接编写正则表达式更难。

当我找到java.text.DecimalFormat时,我就放弃了希望,它明确表示:“我将尽我所能进行解析,我会告诉你我走了多远,所以您可以继续从那一点”。但是,它似乎主要是用于格式化供人类使用的东西,也许是解析由机器编写的东西,而不是解析由人类编写的东西,并且它以许多方式显示。例如,它“支持”科学符号,例如“ 1.2e1”,但是如果使用它,它将坚持数字必须为科学符号,并且如果输入“ 12”,则解析失败。可以尝试通过检查失败的地方并将其之前的内容解析为一个数字来解决此问题,但这很容易出错,并且比为浮点数编写正则表达式更令人讨厌。

同时在C语言中,这只是sscanf(“%f”),而C ++您可以使用字符串流来完成基本相同的操作。 Java真的没有等效功能吗?

java parsing number-formatting string-parsing
1个回答
4
投票

documentationDouble.valueOf(String)实际上包含一个正则表达式,可用于检查字符串是否为double

这里,没有评论:

final String Digits     = "(\\p{Digit}+)";
final String HexDigits  = "(\\p{XDigit}+)";
final String Exp        = "[eE][+-]?"+Digits;
final String fpRegex    =
        ("[\\x00-\\x20]*"+
                "[+-]?(" +
                "NaN|"+
                "Infinity|" +
                "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
                "(\\.("+Digits+")("+Exp+")?)|"+
                "((" +
                "(0[xX]" + HexDigits + "(\\.)?)|" +
                "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
                ")[pP][+-]?" + Digits + "))" +
                "[fFdD]?))" +
                "[\\x00-\\x20]*");

您可以这样使用:

Matcher m = Pattern.compile(fpRegex).matcher(input);
if (m.find()) {
    String doublePartOnly = m.group();
}

通过一些基本测试,我发现正则表达式贪婪,因此它将与1.2e1中的1.2e1hello相匹配,而不仅仅是1.2

© www.soinside.com 2019 - 2024. All rights reserved.