หลังจากคำตอบจาก Casimir ฉันตัดสินใจที่จะเอามันนิดหน่อต่อและกติดตั้งเพื่อใช้งานการหัสอันที่จริการวิเคราะห์ที่ integers เช่นกันรวมทางด้านล่างนี้ มันรวมถึงลบและอีกอย่างสัญลักษณ์แม้ว่าพวกนั้นเป็นอย่างเป็นทางการไม่ใช่ส่วนหนึ่งของจำนวนเต็มจริงที่ถูกระบุไว้ใน JLS;พวกเขาเป็น unary operators.
package nl.owlstead.ifprops;
import java.math.BigInteger;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class JavaIntegerParser {
private static final Pattern BINARY = Pattern.compile("(0b)([01](?:_*[01])*)(L?)", Pattern.CASE_INSENSITIVE);
private static final Pattern OCTAL = Pattern.compile("(0)([0-7](?:_*[0-7])*)(L?)", Pattern.CASE_INSENSITIVE);
private static final Pattern DECIMAL = Pattern.compile("()(0|(?:[1-9](?:_*[0-9])*))(L?)", Pattern.CASE_INSENSITIVE);
private static final Pattern HEXADECIMAL = Pattern.compile("(0x)([0-9a-f](?:_*[0-9a-f])*)(L?)", Pattern.CASE_INSENSITIVE);
// NOTE: OCTAL should be before DECIMAL if this is used to find the pattern
private static final Pattern SIGNED_INTEGER_LITERAL = Pattern.compile(
"(?:([+-])\\s*)?(" +
BINARY + "|" + OCTAL + "|" + DECIMAL + "|" + HEXADECIMAL +
")", Pattern.CASE_INSENSITIVE);
public static int parseJavaInteger(String javaInteger) throws NumberFormatException {
BigInteger value = parseIntegerAsBigInt(javaInteger);
try {
return value.intValueExact();
} catch (@SuppressWarnings("unused") ArithmeticException e) {
throw new NumberFormatException("Number is not between Integer.MIN_VALUE and Integer.MAX_VALUE");
}
}
public static long parseJavaLong(String javaLong) throws NumberFormatException {
BigInteger value = parseIntegerAsBigInt(javaLong);
try {
return value.longValueExact();
} catch (@SuppressWarnings("unused") ArithmeticException e) {
throw new NumberFormatException("Number is not between Integer.MIN_VALUE and Integer.MAX_VALUE");
}
}
private static BigInteger parseIntegerAsBigInt(String javaLiteral) {
Matcher intMatcher = SIGNED_INTEGER_LITERAL.matcher(javaLiteral);
if (!intMatcher.matches()) {
throw new NumberFormatException(javaLiteral + " is not recognized as a Java integer literal");
}
String signGroup = intMatcher.group(1);
String prefixAndValueGroup = intMatcher.group(2);
String radixGroup = "";
String valueGroup = "";
// String longGroup = "";
List<Pattern> patterns = List.of(BINARY, OCTAL, DECIMAL, HEXADECIMAL);
for (Pattern pattern : patterns) {
Matcher specificMatcher = pattern.matcher(prefixAndValueGroup);
if (specificMatcher.matches()) {
radixGroup = specificMatcher.group(1);
valueGroup = specificMatcher.group(2);
// longGroup = specificMatcher.group(3);
break;
}
}
if (valueGroup == null) {
throw new RuntimeException("Number both matches but doesn't contain a value (parser error)");
}
BigInteger sign = signGroup != null && signGroup.matches("-") ? BigInteger.ONE.negate() : BigInteger.ONE;
int radix;
switch (radixGroup.toLowerCase()) {
case "0b":
radix = 2;
break;
case "0":
radix = 8;
break;
case "":
radix = 10;
break;
case "0x":
radix = 16;
break;
default:
throw new RuntimeException();
}
BigInteger value = new BigInteger(valueGroup.replaceAll("_", ""), radix).multiply(sign);
return value;
}
}
ฉันยังพยายามจะใช้รหัสหายหลาย integers อกจากเป็นข้อความแต่นั่นไม่ดีเลย-นายเห็นแม่สาวน้อย ปัญหาก็คือบางอย่างนั้นไม่ถูกต้อง literals อย่างเช่น 0__0
ได้ใบตอบรับเป็นสองคน literals ด้วยค่าศูนย์;ไม่ใช่สิ่งที่เธอต้องการเป๊ะเลยสิ ดังนั้นโปรดใช้ regex เพียงเพื่อระบุสิ่งที่ผิดปกติถ้าเป็นข้อความจริงเป็นจำนวนเต็มแล้วแยกกันที่ integers e.g. ใช้ String.split(SEPARATOR_REGEX)
.
ขำพอแล้วของสุริยคราสแบบ ide ทำองยอมรับ 0__0
เป็นการยึดตามตัวอักษรแบบนั้แม้ว่ามันจะเป็นอย่างเป็นทางการไม่ใช่ compliant ที่ JLS. ไม่ใช่ biggy แต่ไม่ใช่เรื่องแปลกคนน้อยลง
?
ควรจะเป็น*
?