Java: 如何从某个字符串位置解析double并获取它后面的char的位置?
Java: How to parse double from certain string position and get the position of the char after it?
我想要 C++ 中类似于 std::stod
的东西。
我发现的最接近的东西是 DecimalFormat
class,但它的大问题是它的行为与 Double.parseDouble()
不同。例如,它将 3.14E+2
解析为 3.14
而不是 314
。虽然 Double.parseDouble()
对这两种情况给出了相同的答案,但这是我想要的行为。并且仅用 E
替换所有 E+
并不是一个理想的选择(它可能会破坏其他东西)。
所以基本上我想要 Double.parseDouble()
能够设置起始位置并返回结束位置。在 Java 中是否有某种方法可以在不重新实现整个双重解析例程的情况下实现这一点?
扫描仪class与您的要求非常接近:
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
我想要 C++ 中类似于 std::stod
的东西。
我发现的最接近的东西是 DecimalFormat
class,但它的大问题是它的行为与 Double.parseDouble()
不同。例如,它将 3.14E+2
解析为 3.14
而不是 314
。虽然 Double.parseDouble()
对这两种情况给出了相同的答案,但这是我想要的行为。并且仅用 E
替换所有 E+
并不是一个理想的选择(它可能会破坏其他东西)。
所以基本上我想要 Double.parseDouble()
能够设置起始位置并返回结束位置。在 Java 中是否有某种方法可以在不重新实现整个双重解析例程的情况下实现这一点?
扫描仪class与您的要求非常接近:
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