Вот еще одно решение, основанное на 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 на самом деле не представляется в виде двойного числа в точности как 5.6, а как 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 илистоит?Должна быть хотя бы одна цифра для представления дробной части, и помимо этого столько, но только столько, больше цифр, сколько необходимо для уникального различия значения аргумента от смежных значений типа double. То есть предположим, чтоx - точное математическое значение, представленное десятичным представлением, полученным этим методом для конечного ненулевого аргумента d.Тогда d должно быть двойным значением, ближайшим к x;или если два двойных значения одинаково близки к x, то d должно быть одним из них, а младший значащий бит значенияи d должен быть 0.
[...]
Код для получения символов "5.6"
сводится к FloatingDecimal.getChars
:
private int getChars(char[] result) {
assert nDigits <= 19 : nDigits; // generous bound on size of 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) {
// print digits.digits.
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;
}
// decExponent has 1, 2, or 3, digits
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;
}