十进制值问题

Decimal value issue

我有一个非常烦人的任务要做,并且坚持了下来。 所以:我需要编写一个函数来返回小数点后的浮点数的值。 例如:参数为 be:5.456-> 返回值为 be:456.

我不能使用字符串(当然这样会很容易)。

你有什么建议吗?

需要一些步骤才能使用 floatdouble 等原语。如果允许您使用 BigDecimal,这只是一行代码。

给定 double d = 5.456;

  • 首先,把浮点数前面的部分剪掉。
    • int full = (int)d; 执行此操作,这将是 5
    • 从中减去全部:d-full 现在只是点之后的部分,所以 .456
  • 现在使用循环将值乘以 10,直到“点后”部分为 0。

这里的特殊之处在于,当您使用 double 时,您会遇到浮点精度问题。这意味着 d 将具有介于两者之间的值 0.4560000000000004。为了解决这个问题,让我们引入一个 epsilon。

完整代码如下所示:

private static final double EPS = 1e-5;
public static void main(String[] args) {
    double d = 5.456;
    System.out.println(afterDot(d));
}

private static int afterDot(double d) {
    d = getDecimals(d);
    while(getDecimals(d) > EPS){ //decimals will likely never be 0 because of precision, so compare with a really small EPS instead of 0
        d *= 10;
    }
    //cast the result to an int to cut off the double precision issues
    return (int)d;
}

private static double getDecimals(double d) {
    int full = (int) d;
    d = d-full;
    return d;
}

这会打印 456。我非常确定这可以以某种方式进行优化,但这是一个有效的初稿。

你想要的是余数,乘以 10 直到余数为 0。使用 BigDecimal 来防止看起来像这样的舍入问题:

final BigDecimal input = new BigDecimal("5.456");
BigDecimal x = input.remainder(BigDecimal.ONE);
while (x.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) > 0) {
    x = x.multiply(new BigDecimal(10));
}
System.out.println(x.longValue());

这里有两种不针对浮点异常进行调整的方法。

double s = 5.456;
System.out.println(s%1);

System.out.println(s-(int)s);

同时打印

0.4560000000000004

或使用BigDecimal并调整比例并减去整数值。

System.out.println(BigDecimal.valueOf(s)
      .setScale(3)
      .subtract(BigDecimal.valueOf((int)s)));

打印

.456