【问题标题】:parse non-negative doubles解析非负双打
【发布时间】:2011-04-05 19:00:38
【问题描述】:

我需要一个函数,它将接受字符串和整数,指示非负双精度或整数的位置并返回数字或空值。如果有 '+' 则返回 null。

例子

2.1      , 0 -> 2.1
+2.1     , 0 -> null
-1       , 0 -> null
-1.2     , 1 -> 1.2
qwa56sdf , 3 -> 56

最优雅的方法是什么? 谢谢。

更新 我需要这样的代码,但更好)

    Number parse(String str, int pos){
        Matcher m = Pattern.compile("^(\\d+(?:\\.\\d+)?)").matcher(str);
        m.region(pos, str.length());
        if(m.find()){
            return Double.parseDouble(m.group());
        } else {
            return null;
        }
    }

【问题讨论】:

  • 为什么您的第三个示例返回 null?
  • 因为它必须是非负数。
  • 那么,为什么第四个不为空呢?
  • 因为它从第二个字符开始解析。

标签: java string parsing double number-formatting


【解决方案1】:

你可以试试:

public static void main(String[] args) {
  System.out.println(parse("2.1", 0));
  System.out.println(parse("+2.1", 0));
  System.out.println(parse("-1", 0));
  System.out.println(parse("-1.2", 1));
  System.out.println(parse("qwa56sdf", 3));
}

private static Double parse(String string, int index) {
  if (string.charAt(index) == '-' || string.charAt(index) == '+') {
    return null;
  }
  try {
    return Double.parseDouble(string.substring(index).replaceAll("[^\\d.]", ""));
  }
  catch (NumberFormatException e) {
    return null;
  }
}

我不得不用 replace all 去除尾随的非数字字符,因为它们会导致 NumberFormatException 并且会像上一个示例中的输入一样返回 null。

编辑: 对于评论中的情况,您的另一种选择可能是检查每个字符

private static Double parse(String string, int index) {
    String finalString = "";
    boolean foundSeparator = false;
    for (char c : string.substring(index).toCharArray()) {
        if (c == '.') {
            if (foundSeparator) {
                break;
            }
            else {
                foundSeparator = true;
            }
        }
        else if (!Character.isDigit(c)) {
            break;
        }
        finalString += c;
    }
    if (finalString == "") {
        return null;
    }
    return Double.parseDouble(finalString);
}

【讨论】:

  • 谢谢,但是像 parse("qwe5a6asf", 3) 这样的输入有问题
  • 我猜在这个输入中你只想匹配'5',它是那个字符串中的第一个有效数字。我认为更新后的版本也应该适用于这种情况。
  • 是的,我需要类似第二个变体的东西。但我认为 NumberFormat 或类似的东西必须有更好的解决方案。
【解决方案2】:

您需要结合使用String.substring() 方法从字符串中的指定位置开始,并使用NumberFormat 类来解析数字。

【讨论】:

  • 谢谢。实际上,NumberFormat 有 indexPosition 的方法解析,但是 '+' 和 '-' 这样的字符存在问题。
【解决方案3】:

如果这在功能上是正确的,那么在我看来它已经足够优雅了。您可能希望使 Pattern 成为最终类成员,因为您只需要编译一次。而且该地区可能不需要:

Matcher m = pattern.matcher(str.substring(pos));

另一种选择是从一个长度为 1 字符的子字符串开始,并将其增长到不再解析:

if ( str.charAt(pos) == '+' || str.charAt(pos) == '-' ) {
    //special cases
    return null;
}
Double val = null;
for ( int i = pos+1; i <= str.length(); i++ ) {
    try {
       val = Double.parseDouble(str.substring(pos, i)) {
    }  catch (NumberFormatException e) {
       break;
    }
}
return val;

它有点简单,但在性能方面也很幼稚。一个可读性较差但性能更高的解决方案是自己找到双精度的结尾,然后通过一次查看一个字符来进行解析。

【讨论】:

  • 谢谢,它会工作,但我认为必须有更好的解决方案。
【解决方案4】:

还有Scanner 类。其中特别具有读取原语的方法,例如scanner.hasNextDouble()scanner.nextDouble()。您仍然需要检查 + 或 -,因为这仍然会通过检查。

【讨论】:

  • 谢谢,但对于扫描仪,我必须指定分隔符,但我不能。
  • 当然可以,任何不是数字或点的东西。 “[^0-9.]”
  • 是的,我可以使用分隔符,但我想从像“1.2.3”这样的文本解析结果“1.2”,而不是空。
【解决方案5】:
public static Double parseDouble(String input, int fromIndex) {
    Matcher matcher = Pattern.compile("\\d*\\.?\\d+")
        .matcher(input.substring(fromIndex));
    return matcher.lookingAt() ? Double.parseDouble(matcher.group()) : null;
}

【讨论】:

  • 谢谢。这是一个很好的解决方案,但是有很多程序员不会理解它。
【解决方案6】:

我认为以下实现对于您的一组要求会更优雅。我正在使用 java.text.NumberFormat 类进行解析。

    private static Number parse(String text, int position){
        Number value=null;
        NumberFormat nf = NumberFormat.getInstance();
        try {
            value = nf.parse(text,new ParsePosition(position));
            if (value.intValue() < 0)
                value = null;
        } catch (Exception e) {
            value = null;
        }
        return value;
   }

【讨论】:

  • 谢谢。但实际上我不喜欢在非异常流程中使用异常。
  • parse() 方法只抛出 ParseException 以防它无法解析输入表达式,例如“+21”。这是完全有效的,应该被抓住和处理。在我上面的一段代码中,我错误地使用了通用异常而不是 ParseException。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-05
  • 1970-01-01
  • 2017-02-13
相关资源
最近更新 更多