
com.penglecode.common.util.NumberUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons Show documentation
Show all versions of commons Show documentation
commons is a little java tool to make your development easier in your work.
The newest version!
package com.penglecode.common.util;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import org.springframework.util.Assert;
/**
* 数字工具类
*
* @author pengpeng
* @date 2014年7月19日 下午6:58:21
* @version 1.0
*/
public class NumberUtils {
/**
* 判断字符串是否是数字
*
* @param str
* @return
*/
public static boolean isDigits(String str) {
if (StringUtils.isEmpty(str)) {
return false;
}
for (int i = 0; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
/**
* 判断字符串是否可以表示成一个Java Number类型
* 例如:123L、3.14f、2.0d、0x123
*
* @param str
* @return
*/
public static boolean isNumber(String str) {
if (StringUtils.isEmpty(str)) {
return false;
}
char[] chars = str.toCharArray();
int sz = chars.length;
boolean hasExp = false;
boolean hasDecPoint = false;
boolean allowSigns = false;
boolean foundDigit = false;
// deal with any possible sign up front
int start = (chars[0] == '-') ? 1 : 0;
if (sz > start + 1 && chars[start] == '0' && chars[start + 1] == 'x') {
int i = start + 2;
if (i == sz) {
return false; // str == "0x"
}
// checking hex (it can't be anything else)
for (; i < chars.length; i++) {
if ((chars[i] < '0' || chars[i] > '9')
&& (chars[i] < 'a' || chars[i] > 'f')
&& (chars[i] < 'A' || chars[i] > 'F')) {
return false;
}
}
return true;
}
sz--; // don't want to loop to the last char, check it afterwords
// for type qualifiers
int i = start;
// loop to the next to last char or to the last char if we need another digit to
// make a valid number (e.g. chars[0..5] = "1234E")
while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
if (chars[i] >= '0' && chars[i] <= '9') {
foundDigit = true;
allowSigns = false;
} else if (chars[i] == '.') {
if (hasDecPoint || hasExp) {
// two decimal points or dec in exponent
return false;
}
hasDecPoint = true;
} else if (chars[i] == 'e' || chars[i] == 'E') {
// we've already taken care of hex.
if (hasExp) {
// two E's
return false;
}
if (!foundDigit) {
return false;
}
hasExp = true;
allowSigns = true;
} else if (chars[i] == '+' || chars[i] == '-') {
if (!allowSigns) {
return false;
}
allowSigns = false;
foundDigit = false; // we need a digit after the E
} else {
return false;
}
i++;
}
if (i < chars.length) {
if (chars[i] >= '0' && chars[i] <= '9') {
// no type qualifier, OK
return true;
}
if (chars[i] == 'e' || chars[i] == 'E') {
// can't have an E at the last byte
return false;
}
if (chars[i] == '.') {
if (hasDecPoint || hasExp) {
// two decimal points or dec in exponent
return false;
}
// single trailing decimal point after non-exponent is ok
return foundDigit;
}
if (!allowSigns
&& (chars[i] == 'd'
|| chars[i] == 'D'
|| chars[i] == 'f'
|| chars[i] == 'F')) {
return foundDigit;
}
if (chars[i] == 'l'
|| chars[i] == 'L') {
// not allowing L with an exponent or decimal point
return foundDigit && !hasExp && !hasDecPoint;
}
// last character is illegal
return false;
}
// allowSigns is true iff the val ends in 'E'
// found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
return !allowSigns && foundDigit;
}
/**
* 将抽象的Number转换为实际的某个特定类型
*
* @param number
* @param targetClass
* @return
* @throws IllegalArgumentException
*/
@SuppressWarnings("unchecked")
public static T convertNumber(Number number, Class targetClass) {
Assert.notNull(number, "Parameter 'number' must be not null");
Assert.notNull(targetClass, "Parameter 'targetClass' must be not null");
if (targetClass.isInstance(number)) {
return (T) number;
}
else if (targetClass.equals(Byte.class)) {
long value = number.longValue();
if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
raiseOverflowException(number, targetClass);
}
return (T) new Byte(number.byteValue());
}
else if (targetClass.equals(Short.class)) {
long value = number.longValue();
if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
raiseOverflowException(number, targetClass);
}
return (T) new Short(number.shortValue());
}
else if (targetClass.equals(Integer.class)) {
long value = number.longValue();
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
raiseOverflowException(number, targetClass);
}
return (T) new Integer(number.intValue());
}
else if (targetClass.equals(Long.class)) {
return (T) new Long(number.longValue());
}
else if (targetClass.equals(BigInteger.class)) {
if (number instanceof BigDecimal) {
return (T) ((BigDecimal) number).toBigInteger();
}
else {
return (T) BigInteger.valueOf(number.longValue());
}
}
else if (targetClass.equals(Float.class)) {
return (T) new Float(number.floatValue());
}
else if (targetClass.equals(Double.class)) {
return (T) new Double(number.doubleValue());
}
else if (targetClass.equals(BigDecimal.class)) {
return (T) new BigDecimal(number.toString());
}
else {
throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" +
number.getClass().getName() + "] to unknown target class [" + targetClass.getName() + "]");
}
}
private static void raiseOverflowException(Number number, Class> targetClass) {
throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" +
number.getClass().getName() + "] to target class [" + targetClass.getName() + "]: overflow");
}
/**
* 将字符串类型的数字转换为实际的目标类型
*
* @param text
* @param targetClass
* @return
*/
@SuppressWarnings("unchecked")
public static T parseNumber(String text, Class targetClass) {
Assert.notNull(text, "Parameter 'text' must be not null!");
Assert.notNull(targetClass, "Parameter 'targetClass' must be not null!");
String trimmed = text.replaceAll(" ", "");
if (targetClass.equals(Byte.class)) {
return (T) (isHexNumber(trimmed) ? Byte.decode(trimmed) : Byte.valueOf(trimmed));
}
else if (targetClass.equals(Short.class)) {
return (T) (isHexNumber(trimmed) ? Short.decode(trimmed) : Short.valueOf(trimmed));
}
else if (targetClass.equals(Integer.class)) {
return (T) (isHexNumber(trimmed) ? Integer.decode(trimmed) : Integer.valueOf(trimmed));
}
else if (targetClass.equals(Long.class)) {
return (T) (isHexNumber(trimmed) ? Long.decode(trimmed) : Long.valueOf(trimmed));
}
else if (targetClass.equals(BigInteger.class)) {
return (T) (isHexNumber(trimmed) ? decodeBigInteger(trimmed) : new BigInteger(trimmed));
}
else if (targetClass.equals(Float.class)) {
return (T) Float.valueOf(trimmed);
}
else if (targetClass.equals(Double.class)) {
return (T) Double.valueOf(trimmed);
}
else if (targetClass.equals(BigDecimal.class) || targetClass.equals(Number.class)) {
return (T) new BigDecimal(trimmed);
}
else {
throw new IllegalArgumentException(
"Cannot convert String [" + text + "] to target class [" + targetClass.getName() + "]");
}
}
/**
* 将字符串类型的数字转换为实际的带有格式的目标类型
*
* @param text
* @param targetClass
* @param numberFormat
* @return
*/
public static T parseNumber(String text, Class targetClass, NumberFormat numberFormat) {
if (numberFormat != null) {
Assert.notNull(text, "Parameter 'text' must be not null!");
Assert.notNull(targetClass, "Parameter 'targetClass' must be not null!");
DecimalFormat decimalFormat = null;
boolean resetBigDecimal = false;
if (numberFormat instanceof DecimalFormat) {
decimalFormat = (DecimalFormat) numberFormat;
if (BigDecimal.class.equals(targetClass) && !decimalFormat.isParseBigDecimal()) {
decimalFormat.setParseBigDecimal(true);
resetBigDecimal = true;
}
}
try {
Number number = numberFormat.parse(text.replaceAll(" ", ""));
return convertNumber(number, targetClass);
}
catch (ParseException ex) {
throw new IllegalArgumentException("Could not parse number: " + ex.getMessage());
}
finally {
if (resetBigDecimal) {
decimalFormat.setParseBigDecimal(false);
}
}
}
else {
return parseNumber(text, targetClass);
}
}
private static boolean isHexNumber(String value) {
int index = (value.startsWith("-") ? 1 : 0);
return (value.startsWith("0x", index) || value.startsWith("0X", index) || value.startsWith("#", index));
}
/**
* 将字符串类型的数字转换成BigInteger,支持十进制、十六进制、八进制写法
*
* @param value
* @return
*/
private static BigInteger decodeBigInteger(String value) {
int radix = 10;
int index = 0;
boolean negative = false;
if (value.startsWith("-")) {
negative = true;
index++;
}
if (value.startsWith("0x", index) || value.startsWith("0X", index)) {
index += 2;
radix = 16;
}
else if (value.startsWith("#", index)) {
index++;
radix = 16;
}
else if (value.startsWith("0", index) && value.length() > 1 + index) {
index++;
radix = 8;
}
BigInteger result = new BigInteger(value.substring(index), radix);
return (negative ? result.negate() : result);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy