我想要一些类似于C ++的std::stod
。
我发现的最接近的是DecimalFormat
类,但最重要的是它与Double.parseDouble()
的行为不同。例如,它将3.14E+2
解析为3.14
而不是314
。虽然Double.parseDouble()
给出了两种情况相同的答案,但这是我想要的行为。用E+
替换所有E
并不是一个理想的选择(它可能会打破其他事情)。
所以基本上我希望Double.parseDouble()
能够设置起始位置并返回结束位置。有没有办法在Java中实现这一点而不重新实现整个双解析例程?
答案 0 :(得分:1)
扫描仪课程与您的要求非常接近:
import java.util.*;
import java.lang.reflect.*;
public class ScanFloat {
public static void main(String args[]) throws Exception {
String str = "foo 3.14E+2 xx";
int startPos = 4;
Scanner s = new Scanner(str.substring(4));
s.useLocale(Locale.ENGLISH);
System.out.println(s.nextDouble());
System.out.println("endingPos: " + (startPos + getPos(s)));
}
static int getPos(Scanner s) throws Exception {
Field f = Scanner.class.getDeclaredField("position");
f.setAccessible(true);
return (int) f.get(s);
}
}
输出:
314.0
endingPos: 11
但是,输入"foo 3.14E+2xx"
会抛出异常。根据您的使用情况,它可能会也可能不会。
使用正则表达式可以解决这个问题,并且它也不是那么难,只要你使用patterns from the documentation I linked:
import java.util.regex.*;
import java.util.concurrent.atomic.AtomicInteger;
public class RegexFloat {
public static void main(String args[]) {
String testString = "foo 3.14E+2xx";
AtomicInteger parsePos = new AtomicInteger(0);
Double d = parseDouble(testString, parsePos);
System.out.println(d);
System.out.println(parsePos);
}
static Double parseDouble(String str, AtomicInteger parsePos) {
Pattern pattern = Pattern.compile(fpRegex);
Matcher m = pattern.matcher(str.substring(parsePos.get()));
if (m.find()) {
parsePos.set(m.end(1));
return Double.parseDouble(m.group(1));
}
return null;
}
// or Pattern.compile(String.format(".{%d}%s", parsePos.get(), fpRegex));
// if you want to avoid substring above for some reason and
// want to add offset into the pattern
static final String Digits = "(\\p{Digit}+)";
static final String HexDigits = "(\\p{XDigit}+)";
// an exponent is 'e' or 'E' followed by an optionally
// signed decimal integer.
static final String Exp = "[eE][+-]?"+Digits;
static final String fpRegex =
("[\\x00-\\x20]*"+ // Optional leading "whitespace"
"[+-]?(" + // Optional sign character
"NaN|" + // "NaN" string
"Infinity|" + // "Infinity" string
// A decimal floating-point string representing a finite positive
// number without a leading sign has at most five basic pieces:
// Digits . Digits ExponentPart FloatTypeSuffix
//
// Since this method allows integer-only strings as input
// in addition to strings of floating-point literals, the
// two sub-patterns below are simplifications of the grammar
// productions from section 3.10.2 of
// The Java™ Language Specification.
// Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
"((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
// . Digits ExponentPart_opt FloatTypeSuffix_opt
"(\\.("+Digits+")("+Exp+")?)|"+
// Hexadecimal strings
"((" +
// 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
"(0[xX]" + HexDigits + "(\\.)?)|" +
// 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
"(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
")[pP][+-]?" + Digits + "))" +
"[fFdD]?))" +
"[\\x00-\\x20]*");// Optional trailing "whitespace"
}
输出:
314.0
11