我有一项服务可以接收来自外部世界的双打。我确定所有双打小数点后只有 4 位数字。为了保持精度,我想将传入的双精度数转换为整数,使用整数,然后将它们转换回双精度数以返回。我在理论上看到,知道输入总是在小数点后有 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,但我认为它在这里并不重要。
使用参考
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));
}