unb*_*eli 31
boolean isDouble(String str) {
try {
Double.parseDouble(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
aio*_*obe 13
在源代码中Double有一个关于此的说明:
[...] 为了避免在无效字符串上调用此方法并
NumberFormatException抛出,下面的正则表达式可用于筛选输入字符串: [...]
后面的正则表达式的最终形式很长:
[\x00-\x20]*[+-]?(NaN|Infinity|((((\p{Digit}+)(\.)?((\p{Digit}+)?)([eE][+-]?(\p{Digit}+))?)|(\.((\p{Digit}+))([eE][+-]?(\p{Digit}+))?)|(((0[xX](\p{XDigit}+)(\.)?)|(0[xX](\p{XDigit}+)?(\.)(\p{XDigit}+)))[pP][+-]?(\p{Digit}+)))[fFdD]?))[\x00-\x20]*
Run Code Online (Sandbox Code Playgroud)
但是,使用这种方法,您可以轻松地排除一些特殊的双打,例如Infinity和NaN它们都被接受Double.parseDouble.例如这样:
String regExp = "[\\x00-\\x20]*[+-]?(((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)|(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*";
boolean matches = yourString.matches(regExp);
Run Code Online (Sandbox Code Playgroud)
使用a Scanner将明显慢于使用Double.parseDouble(String s).
private static Random rand = new Random();
private static final String regExp = "[\\x00-\\x20]*[+-]?(((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)|(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*";
private static final Pattern pattern = Pattern.compile(regExp);
public static void main(String[] args) {
int trials = 50000;
String[] values = new String[trials];
// initialize the array
// about half the values will be parsable as double
for( int i = 0; i < trials; ++i ) {
double d = rand.nextDouble();
boolean b = rand.nextBoolean();
values[i] = (b ? "" : "abc") + d;
}
long start = System.currentTimeMillis();
int parseCount = 0;
for( int i = 0; i < trials; ++i ) {
if( isDoubleParse(values[i]) ) {
parseCount++;
}
}
long end = System.currentTimeMillis();
long elapsed = end - start;
System.out.println("Elapsed time parsing: " + elapsed + " ms");
System.out.println("Doubles: " + parseCount);
// reset the timer for the next run
start = System.currentTimeMillis();
int scanCount = 0;
for( int i = 0; i < trials; ++i ) {
if( isDoubleScan(values[i]) ) {
scanCount++;
}
}
end = System.currentTimeMillis();
elapsed = end - start;
System.out.println("Elapsed time scanning: " + elapsed + " ms");
System.out.println("Doubles: " + scanCount);
// reset the timer for the next run
start = System.currentTimeMillis();
int regexCount = 0;
for( int i = 0; i < trials; ++i ) {
if( isDoubleRegex(values[i]) ) {
regexCount++;
}
}
end = System.currentTimeMillis();
elapsed = end - start;
System.out.println("Elapsed time regex (naive): " + elapsed + " ms");
System.out.println("Doubles: " + naiveRegexCount);
// reset the timer for the next run
start = System.currentTimeMillis();
int compiledRegexCount = 0;
for( int i = 0; i < trials; ++i ) {
if( isDoubleCompiledRegex(values[i]) ) {
compiledRegexCount++;
}
}
end = System.currentTimeMillis();
elapsed = end - start;
System.out.println("Elapsed time regex (compiled): " + elapsed + " ms");
System.out.println("Doubles: " + compiledRegexCount);
}
public static boolean isDoubleParse(String s) {
if( s == null ) return false;
try {
Double.parseDouble(s);
return true;
} catch (NumberFormatException e) {
return false;
}
}
public static boolean isDoubleScan(String s) {
Scanner scanner = new Scanner(s);
return scanner.hasNextDouble();
}
public static boolean isDoubleRegex(String s) {
return s.matches(regExp);
}
public static boolean isDoubleCompiledRegex(String s) {
Matcher m = pattern.matcher(s);
return m.matches();
}
Run Code Online (Sandbox Code Playgroud)
当我运行上面的代码时,我得到以下输出:
经过时间解析:235毫秒
双打:24966
经过时间扫描:
31358 毫秒双打:24966
经过时间正则表达式(天真):1829毫秒
双打:24966
经过时间正则表达式(已编译):109毫秒
双打:24966
鉴于正则表达式的复杂性,正则表达式方法运行得相当快,但仍然没有简单解析使用那么快Double.parseDouble(s).正如评论中指出的那样,有一些值NaN可以通过解析器而不是.
按照@ Gabe的建议预编译正则表达式会有所不同.编译的正则表达式方法现在是明显的赢家.
您可以创建Scanner(String)并使用该hasNextDouble()方法.从它的javadoc:
返回
true此扫描器输入中的下一个标记是否可以使用该nextDouble()方法解释为double值.扫描仪不会超过任何输入.
例如,这个片段:
List<String> values = Arrays.asList("foo", "1", "2.3", "1f", "0.2d", "3.14");
for (String source : values) {
Scanner scanner = new Scanner(source);
System.out.println(String.format("%4s: %s", source, scanner.hasNextDouble()));
}
Run Code Online (Sandbox Code Playgroud)
会产生以下输出:
foo: false 1: true 2.3: true 1f: false 0.2d: false 3.14: true
public boolean isDouble(String value) {
try {
Double.parseDouble(value);
return true;
} catch (NumberFormatException e) {
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用Apache Commons Lang的util类:
NumberUtils.isNumber(aString);
Run Code Online (Sandbox Code Playgroud)
它是null安全的,不需要使用try-catch块.
注意:对于解析双精度数,如果小数点分隔符是点,则它可以工作.
编辑: isNumber已弃用,将从Lang 4.0中删除
更好用:
NumberUtils.isCreatable(aString);
Run Code Online (Sandbox Code Playgroud)
您可以尝试用以下方法解析它Double.parseDouble(String s)
如果解析成功,则返回双精度值;如果不可解析,则返回异常。
因此,您可以将整个事情包装在一个包含 try-catch 的函数中,如果出现异常则返回 false,如果获得实际值则返回 true。
| 归档时间: |
|
| 查看次数: |
60805 次 |
| 最近记录: |