我在String
中有一个十六进制格式的大数字(带小数点),我想将其转换为BigDecimal.
值示例:0xcc.ccdp+1600
在BigDecimal
类中,我没有看到任何函数以十六进制格式表示数字的字符串作为输入并返回相应的BigDecimal.
有没有办法将大十六进制数从String
转换为BigDecimal?
最佳答案
我很惊讶BigDecimal
还不支持此功能。我写了以下内容,我认为应该可行。它通过了我的初步测试(0xcc.ccdp+0
,0xcc.ccdp+1
,0xcc.ccdp+16
,0xcc.ccdp+256
和您的0xcc.ccdp+1600
,还有一些负面的指标,从-1
到-16
),但是在用于生产代码之前应进行更彻底的测试。
private final static BigInteger TWO = BigInteger.valueOf(2);
private final static BigDecimal MINUS_ONE = new BigDecimal(-1);
public static BigDecimal toBigDecimal(String hex) {
// handle leading sign
BigDecimal sign = null;
if (hex.startsWith("-")) {
hex = hex.substring(1);
sign = MINUS_ONE;
} else if (hex.startsWith("+")) {
hex = hex.substring(1);
}
// constant must start with 0x or 0X
if (!(hex.startsWith("0x") || hex.startsWith("0X"))) {
throw new IllegalArgumentException(
"not a hexadecimal floating point constant");
}
hex = hex.substring(2);
// ... and end in 'p' or 'P' and an exponent
int p = hex.indexOf("p");
if (p < 0) p = hex.indexOf("P");
if (p < 0) {
throw new IllegalArgumentException(
"not a hexadecimal floating point constant");
}
String mantissa = hex.substring(0, p);
String exponent = hex.substring(p+1);
// find the hexadecimal point, if any
int hexadecimalPoint = mantissa.indexOf(".");
int hexadecimalPlaces = 0;
if (hexadecimalPoint >= 0) {
hexadecimalPlaces = mantissa.length() - 1 - hexadecimalPoint;
mantissa = mantissa.substring(0, hexadecimalPoint) +
mantissa.substring(hexadecimalPoint + 1);
}
// reduce the exponent by 4 for every hexadecimal place
int binaryExponent = Integer.valueOf(exponent) - (hexadecimalPlaces * 4);
boolean positive = true;
if (binaryExponent < 0) {
binaryExponent = -binaryExponent;
positive = false;
}
BigDecimal base = new BigDecimal(new BigInteger(mantissa, 16));
BigDecimal factor = new BigDecimal(TWO.pow(binaryExponent));
BigDecimal value = positive? base.multiply(factor) : base.divide(factor);
if (sign != null) value = value.multiply(sign);
return value;
}
我在MIT许可下拥有released this on github。有单元测试,但只有很少的一组。
如果您发现任何情况下返回的值不正确,请告诉我们。