[英]Java : How to count the number of decimals contained in a double value that represent money?
[英]How to find out if the value contained in a string is double or not
在Java中,我試圖找出字符串中包含的值是否為double?
boolean isDouble(String str) {
try {
Double.parseDouble(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
[...] 為了避免在無效字符串上調用此方法並拋出
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]*
但是,使用此方法,您可以輕松地排除Double.parseDouble
接受的一些特殊雙精度,如Infinity
和NaN
。 例如這樣:
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);
您可以創建一個Scanner(String)
並使用hasNextDouble()
方法。 從它的javadoc:
如果使用
nextDouble()
方法可以將此掃描器輸入中的下一個標記解釋為double值,則返回true
。 掃描儀不會超過任何輸入。
例如,這個片段:
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()));
}
會產生以下輸出:
foo: false 1: true 2.3: true 1f: false 0.2d: false 3.14: true
使用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();
}
當我運行上面的代碼時,我得到以下輸出:
經過時間解析:235毫秒
雙打:24966
經過時間掃描:31358毫秒
雙打:24966
經過時間正則表達式(天真):1829毫秒
雙打:24966
經過時間正則表達式(已編譯):109毫秒
雙打:24966
鑒於正則表達式的復雜性,正則表達式方法運行得相當快,但仍然不如使用Double.parseDouble(s)
簡單解析那么快。 正如評論中指出的那樣,有一些像NaN
這樣的值可以通過解析器,但可能不應該這樣。
按照@ Gabe的建議預編譯正則表達式會有所不同。 編譯的正則表達式方法現在是明顯的贏家。
public boolean isDouble(String value) {
try {
Double.parseDouble(value);
return true;
} catch (NumberFormatException e) {
return false;
}
}
您可以使用Apache Commons Lang的util類:
NumberUtils.isNumber(aString);
它是null安全的,不需要使用try-catch塊。
注意:對於解析雙精度數,如果小數點分隔符是點,則它可以工作.
編輯: isNumber已棄用,將從Lang 4.0中刪除
更好用:
NumberUtils.isCreatable(aString);
您可以嘗試使用Double.parseDouble(String s)
解析它
如果解析成功則返回double,如果不可解析則返回異常。
所以你可以把整個東西包裝在一個包含try-catch的函數中,如果有異常則返回false,如果你得到一個實際值則返回true。
我建議這樣:
try {
d = Double.parseDouble(myString);
}
catch (NumberFormatException ex) {
// Do something smart here...
}
其他人推測您可能還想知道輸入不是表示為整數。 根據您的要求,這可能會使作業快速而骯臟:
public static void main(String[] args) throws Exception {
System.out.println(isNonIntegerDouble("12")); //false
System.out.println(isNonIntegerDouble("12.1")); //true
System.out.println(isNonIntegerDouble("12.0")); //true
}
public static boolean isNonIntegerDouble(String in) {
try {
Double.parseDouble(in);
} catch (NumberFormatException nfe) {
return false;
}
try {
new BigInteger(in);
} catch (NumberFormatException nfe) {
return true;
}
return false;
}
在這一點上,我覺得字符串匹配將是一個更合適的選擇。
您可以在字符串上使用以下正則表達式:
[-+]?[0-9]*\.?[0-9]*
並查看它是否匹配。
我修改了Jonas的isInteger()方法,為我自己的項目提出了方法isDecimal(),我列出了下面的代碼。
可能有人可以更改添加更多代碼來區分double和float。
雖然我沒有檢查,它應該很快出來,可能比正則表達更好。 唯一的缺陷是在溢出情況等情況下行為不端。
請注意,我參考Bill的帖子是什么是檢查String是否代表Java中的整數的最佳方法?
public boolean isDecimal(String str) {
if (str == null) {
return false;
}
int length = str.length();
if (length == 1 ) {
return false;
}
int i = 0;
if (str.charAt(0) == '-') {
if (length < 3) {
return false;
}
i = 1;
}
int numOfDot = 0;
for (; i < length; i++) {
char c = str.charAt(i);
if (c == '.')
numOfDot++;
else if (c == '/')
return false;
else if (c < '.' || c > '9') {
return false;
}
}
if (numOfDot != 1 )
return false;
return true;
}
如果您可以找到一種方法將數字與字符串隔離,可以使用split方法。 讓我們說num[1] = 25;
然后你可以做這樣的事情來檢查它是否是一個雙倍。
boolean isDouble;
if(num[1].contains(".")){
isDouble = true;
}
else{
isDouble = false;
}
public boolean isDouble( String input )
{
try
{
Double.parseDouble( input );
return true;
}
catch( Exception e)
{
return false;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.