在java中将double分成两部分"integer&fraction"的最佳方法是什么?

Eng*_*uad 12 java math double fractions

我试图通过以下方法分离5.6(例如):

private static double[] method(double d)
{
    int integerPart = 0;
    double fractionPart = 0.0;
    integerPart = (int) d;
    fractionPart = d - integerPart;
    return new double[]{integerPart, fractionPart};
}
Run Code Online (Sandbox Code Playgroud)

但我得到的是:

[0] = 5.0
[1] = 0.5999999999999996
Run Code Online (Sandbox Code Playgroud)

如果不将数字转换为字符串,您对此有何建议?

Boz*_*zho 12

BigDecimal做同样的计算.(使用双精度因其表现而存在精度问题).

  • 构造它new BigDecimal(String.valueOf(yourDouble))(这仍然通过字符串,但部分不通过字符串操作分开)
  • 使用bd.subtract(new BigDecimal(bd.intValue())来确定分数


aio*_*obe 5

这是另一种基于BigDecimal(不经过a String)的解决方案.

private static double[] method(double d) {
    BigDecimal bd = new BigDecimal(d);
    return new double[] { bd.intValue(),
                          bd.remainder(BigDecimal.ONE).doubleValue() };
}
Run Code Online (Sandbox Code Playgroud)

正如您将注意到的那样,您仍然无法获得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() };
}
Run Code Online (Sandbox Code Playgroud)

实际上产量[5.0, 0.6].

然而BigDecimal.valueOf,在大多数JDK(内部)通过调用实现Double.toString.但至少与字符串相关的东西不会使你的代码混乱:-)


评论中的好后续问题:

如果它表示为5.599999999 ...,那么为什么Double.toString(5.6)准确给出"5.6"

Double.toString方法实际上非常复杂.来自以下文件Double.toString:

[...]

m或a的小数部分必须打印多少位?必须有至少一个数来表示小数部分,并且除此之外,需要来唯一地区分型双的相邻值的参数值,作为许多,但仅作为许多,多个数字.也就是说,假设x是由该方法为有限非零参数d生成的十进制表示所表示的精确数学值.那么d必须是最接近x的double值; 或者如果两个double值同样接近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;
}
Run Code Online (Sandbox Code Playgroud)