保持整数的精度,作为双精度传递

问题描述 投票:0回答:1

我有一项服务可以接收来自外部世界的双打。我确定所有双打小数点后只有 4 位数字。为了保持精度,我想将传入的双精度数转换为整数,使用整数,然后将它们转换回双精度数以返回。我在理论上看到,知道输入总是在小数点后有 4 位数字,我根本不应该在这里失去精度,考虑到我只对这些数字应用加法/减法不涉及除法和乘法。

  • 1.2345来找我,我知道1.23456789来不了
  • 我将它乘以 10,000 并在不丢失精度的情况下使用整数
  • 然后我可以将它除以 10,000 并发回,没有 /* 操作,因此我最终得到小数点后相同的 4 位数字

不幸的是我在这里失去了准确性:

    double[] n = {1.3456, 6.0000, 1.9999, 7.0001};
    int[] in = new int[4];
    double[] od = new double[4];
    for (int i=0;i<4;i++) {
        in[i] = (int) (n[i] * 10_000);
    }
    for (int i=0;i<4;i++) {
        od[i] = ((double)in[i] / 10_000.0);
    }
    System.out.println(Arrays.toString(n)); //
    System.out.println(Arrays.toString(in));
    System.out.println(Arrays.toString(od));

..给我

[**1.3456**, 6.0, 1.9999, 7.0001]
[**13455**, 60000, 19999, 70001]
[**1.3455**, 6.0, 1.9999, 7.0001]

..这已经不好了

问题: 是否有可能完全消除这里的精度损失?我只看到一个选项:double > string > integer > operations with integers > construct string > build double,但它相当费力。我正在使用 Java,但我认为它在这里并不重要。

java algorithm floating-point double precision
1个回答
0
投票

使用参考

Double
而不是原始
double
进行输入,并转换为
BigDecimal
以确保准确性。

public static void main(String args[]) {

    Double[] n  = {1.3456, 6.0000, 1.9999, 7.0001};
    int[] in    = new int[4];
    double[] od = new double[4];

    final BigDecimal tenK = BigDecimal.valueOf(10000);

    for (int i=0;i<4;i++) {
        in[i] = BigDecimal.valueOf(n[i]).multiply(tenK).intValue();
    }

    for (int i=0;i<4;i++) {
        od[i] = in[i] / tenK.doubleValue();
    }

    System.out.println(Arrays.toString(n)); 
    System.out.println(Arrays.toString(in));
    System.out.println(Arrays.toString(od));
}

如果转换是一个循环任务,可以提取成一个函数:

public static void main(String args[]) {

    Double[] n  = {1.3456, 6.0000, 1.9999, 7.0001};
    int[] in    = new int[4];
    double[] od = new double[4];

    final BigDecimal tenK = BigDecimal.valueOf(10000);

    final DoubleToIntFunction multiplyBYTenK = d -> BigDecimal.valueOf(d).multiply(tenK).intValue();
    final IntToDoubleFunction divideByTenK   = i -> i / tenK.doubleValue();

    Arrays.setAll(in, i -> multiplyBYTenK.applyAsInt(n[i]));
    Arrays.setAll(od, i -> divideByTenK.applyAsDouble(in[i]));

    System.out.println(Arrays.toString(n)); //
    System.out.println(Arrays.toString(in));
    System.out.println(Arrays.toString(od));
}
© www.soinside.com 2019 - 2024. All rights reserved.