这里有另一个基于BigDecimal
的解决方案(不经过String
)。
private static double[] method(double d) {
BigDecimal bd = new BigDecimal(d);
return new double[] { bd.intValue(),
bd.remainder(BigDecimal.ONE).doubleValue() };
}
如您所见,即使是小数部分,您仍然不会得到仅为
0.6
的输出。(甚至无法将
0.6
存储在
double
中!)这是因为数学上的实数5.6实际上并非精确地表示为一个double类型的数值,而是表示为5.599999...。
您也可以进行以下操作:
private static double[] method(double d) {
BigDecimal bd = BigDecimal.valueOf(d);
return new double[] { bd.intValue(),
bd.remainder(BigDecimal.ONE).doubleValue() };
}
实际上返回的是[5.0, 0.6]
。
BigDecimal.valueOf
在大多数JDK中(内部)通过调用Double.toString
来实现。但至少与字符串相关的内容不会使您的代码混乱 :-)
评论中提出了一个好的后续问题:
如果它表示为5.599999999...,那么为什么Double.toString(5.6)
恰好给出"5.6"
Double.toString
方法实际上非常复杂。从Double.toString
的文档中可以看到:
[...]
对于m或a的小数部分必须打印多少个数字?必须至少有一个数字来表示小数部分,并且除此之外还需要尽可能多但只有这么多位数字,以便唯一地区分类型double的相邻值和参数值。也就是说,假设x是由该方法为有限非零参数d生成的十进制表示所表示的精确数学值。那么d必须是最接近x的double值;或者如果两个double值对x的距离相等,则d必须是它们之一,并且d的有效数字的最低位必须为0。
[...]
获取字符"5.6"
的代码归结为FloatingDecimal.getChars
:
private int getChars(char[] result) {
assert nDigits <= 19 : nDigits;
int i = 0;
if (isNegative) { result[0] = '-'; i = 1; }
if (isExceptional) {
System.arraycopy(digits, 0, result, i, nDigits);
i += nDigits;
} else {
if (decExponent > 0 && decExponent < 8) {
int charLength = Math.min(nDigits, decExponent);
System.arraycopy(digits, 0, result, i, charLength);
i += charLength;
if (charLength < decExponent) {
charLength = decExponent-charLength;
System.arraycopy(zero, 0, result, i, charLength);
i += charLength;
result[i++] = '.';
result[i++] = '0';
} else {
result[i++] = '.';
if (charLength < nDigits) {
int t = nDigits - charLength;
System.arraycopy(digits, charLength, result, i, t);
i += t;
} else {
result[i++] = '0';
}
}
} else if (decExponent <=0 && decExponent > -3) {
result[i++] = '0';
result[i++] = '.';
if (decExponent != 0) {
System.arraycopy(zero, 0, result, i, -decExponent);
i -= decExponent;
}
System.arraycopy(digits, 0, result, i, nDigits);
i += nDigits;
} else {
result[i++] = digits[0];
result[i++] = '.';
if (nDigits > 1) {
System.arraycopy(digits, 1, result, i, nDigits-1);
i += nDigits-1;
} else {
result[i++] = '0';
}
result[i++] = 'E';
int e;
if (decExponent <= 0) {
result[i++] = '-';
e = -decExponent+1;
} else {
e = decExponent-1;
}
if (e <= 9) {
result[i++] = (char)(e+'0');
} else if (e <= 99) {
result[i++] = (char)(e/10 +'0');
result[i++] = (char)(e%10 + '0');
} else {
result[i++] = (char)(e/100+'0');
e %= 100;
result[i++] = (char)(e/10+'0');
result[i++] = (char)(e%10 + '0');
}
}
}
return i;
}