java 检测字符串是否为数字的最优雅方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/359625/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Most elegant way to detect if a String is a number?
提问by Epaga
Is there a better, more elegant (and/or possibly faster) way than
有没有比这更好、更优雅(和/或可能更快)的方法
boolean isNumber = false;
try{
Double.valueOf(myNumber);
isNumber = true;
} catch (NumberFormatException e) {
}
...?
……?
Edit: Since I can't pick two answers I'm going with the regex one because a) it's elegant and b) saying "Jon Skeet solved the problem" is a tautology because Jon Skeet himself is the solution to all problems.
编辑:由于我无法选择两个答案,我将使用正则表达式,因为 a) 它很优雅,并且 b) 说“Jon Skeet 解决了问题”是同义反复,因为 Jon Skeet 本人是所有问题的解决方案。
回答by Jon Skeet
I don't believe there's anything built into Java to do it faster and still reliably, assuming that later on you'll want to actually parse it with Double.valueOf (or similar).
我不相信 Java 中内置了任何东西可以更快且仍然可靠地完成它,假设稍后您将要实际使用 Double.valueOf(或类似方法)解析它。
I'd use Double.parseDouble instead of Double.valueOf to avoid creating a Double unnecessarily, andyou can also get rid of blatantly silly numbers quicker than the exception will by checking for digits, e/E, - and . beforehand. So, something like:
我会使用 Double.parseDouble 而不是 Double.valueOf 来避免不必要地创建 Double,并且您还可以通过检查数字、e/E、- 和 . 预先。所以,像这样:
public boolean isDouble(String value)
{
boolean seenDot = false;
boolean seenExp = false;
boolean justSeenExp = false;
boolean seenDigit = false;
for (int i=0; i < value.length(); i++)
{
char c = value.charAt(i);
if (c >= '0' && c <= '9')
{
seenDigit = true;
continue;
}
if ((c == '-' || c=='+') && (i == 0 || justSeenExp))
{
continue;
}
if (c == '.' && !seenDot)
{
seenDot = true;
continue;
}
justSeenExp = false;
if ((c == 'e' || c == 'E') && !seenExp)
{
seenExp = true;
justSeenExp = true;
continue;
}
return false;
}
if (!seenDigit)
{
return false;
}
try
{
Double.parseDouble(value);
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
Note that despite taking a couple of tries, this stilldoesn't cover "NaN" or hex values. Whether you want those to pass or not depends on context.
请注意,尽管进行了几次尝试,但这仍然没有涵盖“NaN”或十六进制值。您是否希望这些通过与否取决于上下文。
In my experience regular expressions are slower than the hard-coded check above.
根据我的经验,正则表达式比上面的硬编码检查慢。
回答by Jon Skeet
You could use a regex, i.e. something like String.matches("^[\\d\\-\\.]+$");(if you're not testing for negative numbers or floating point numbers you could simplify a bit).
您可以使用正则表达式,即类似的东西String.matches("^[\\d\\-\\.]+$");(如果您不测试负数或浮点数,您可以稍微简化一下)。
Not sure whether that would be faster than the method you outlined though.
不确定这是否会比您概述的方法更快。
Edit:in the light of all this controversy, I decided to make a test and get some data about how fast each of these methods were. Not so much the correctness, but just how quickly they ran.
编辑:鉴于所有这些争议,我决定进行测试并获取有关每种方法的速度的一些数据。与其说是正确性,不如说是他们跑得有多快。
You can read about my results on my blog. (Hint: Jon Skeet FTW).
你可以在我的博客上阅读我的结果。(提示:Jon Skeet FTW)。
回答by Ran Biron
See java.text.NumberFormat(javadoc).
请参阅java.text.NumberFormat(javadoc)。
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
Number myNumber = nf.parse(myString);
int myInt = myNumber.intValue();
double myDouble = myNumber.doubleValue();
回答by Michael Myers
The correct regex is actually given in the Double javadocs:
正确的正则表达式实际上在Double javadocs 中给出:
To avoid calling this method on an invalid string and having a NumberFormatException be thrown, the regular expression below can be used to screen the input string:
为了避免在无效字符串上调用此方法并抛出 NumberFormatException,可以使用下面的正则表达式来筛选输入字符串:
final String Digits = "(\p{Digit}+)";
final String HexDigits = "(\p{XDigit}+)";
// an exponent is 'e' or 'E' followed by an optionally
// signed decimal integer.
final String Exp = "[eE][+-]?"+Digits;
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 the Java Language Specification, 2nd
// edition, section 3.10.2.
// 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"
if (Pattern.matches(fpRegex, myString))
Double.valueOf(myString); // Will not throw NumberFormatException
else {
// Perform suitable alternative action
}
This does not allow for localized representations, however:
但是,这不允许本地化表示:
To interpret localized string representations of a floating-point value, use subclasses of NumberFormat.
要解释浮点值的本地化字符串表示,请使用NumberFormat 的子类。
回答by plinth
Leveraging off Mr. Skeet:
利用 Skeet 先生:
private boolean IsValidDoubleChar(char c)
{
return "0123456789.+-eE".indexOf(c) >= 0;
}
public boolean isDouble(String value)
{
for (int i=0; i < value.length(); i++)
{
char c = value.charAt(i);
if (IsValidDoubleChar(c))
continue;
return false;
}
try
{
Double.parseDouble(value);
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
回答by Nick Holt
Use StringUtils.isDouble(String)in Apache Commons.
StringUtils.isDouble(String)在 Apache Commons 中使用。
回答by Guillaume
I would use the Jakarta commons-lang, as always ! But I have no idea if their implementationis fast or not. It doesnt rely on Exceptions, which might be a good thig performance wise ...
我会一如既往地使用Jakarta commons-lang!但我不知道他们的实施是否很快。它不依赖于异常,这可能是一个很好的性能明智......
回答by Randy Stegbauer
Most of these answers are somewhatacceptable solutions. All of the regex solutions have the issue of not being correctfor all cases you may care about.
大多数这些答案都有点接受的解决办法。所有正则表达式解决方案都存在对您可能关心的所有情况都不正确的问题。
If you really want to ensure that the String is a valid number, then I would use your own solution. Don't forget that, I imagine, that most of the time the String will be a validnumber and won't raise an exception. So most of the time the performance will be identical to that of Double.valueOf().
如果你真的想确保 String 是一个有效的数字,那么我会使用你自己的解决方案。别忘了,我想,大多数时候 String 将是一个有效数字并且不会引发异常。所以大多数时候性能与 Double.valueOf() 相同。
I guess this really isn't an answer, except that it validates your initial instinct.
我想这真的不是一个答案,只是它验证了你最初的直觉。
Randy
兰迪
回答by Randy Stegbauer
I prefer using a loop over the Strings's char[] representation and using the Character.isDigit() method. If elegance is desired, I think this is the most readable:
我更喜欢在字符串的 char[] 表示上使用循环并使用 Character.isDigit() 方法。如果需要优雅,我认为这是最易读的:
package tias;
public class Main {
private static final String NUMERIC = "123456789";
private static final String NOT_NUMERIC = "1L5C";
public static void main(String[] args) {
System.out.println(isStringNumeric(NUMERIC));
System.out.println(isStringNumeric(NOT_NUMERIC));
}
private static boolean isStringNumeric(String aString) {
if (aString == null || aString.length() == 0) {
return false;
}
for (char c : aString.toCharArray() ) {
if (!Character.isDigit(c)) {
return false;
}
}
return true;
}
}
}
回答by bruno conde
Following Phill's answer can I suggest another regex?
按照菲尔的回答,我可以建议另一个正则表达式吗?
String.matches("^-?\d+(\.\d+)?$");

