提问人:MiamiBeach 提问时间:3/16/2023 最后编辑:LWChrisMiamiBeach 更新时间:3/22/2023 访问量:117
保持整数的精度,以双精度形式传递
Keeping precision of integers, passed as doubles
问:
我有一项服务,从外部世界接收双倍。我确信所有双打在小数点后只有 4 位数字。需要强调的是,向我发送数据的原始系统使用 5 位整数,因此这 5 位数字“后面”的所有数据都是毫无意义且具有误导性的。为了保持精确度,我想将传入的双精度转换为整数,使用整数,然后将它们转换回双精度以返回。我看到从理论上讲,知道输入总是在小数点后有 4 位数字,考虑到我只对这些数字应用加法/减法,我根本不应该在这里失去精度。不涉及除法和乘法。
即
- 收到像 1.2345 这样的双倍(我知道无法收到 1.23456789)
- 我将其乘以 10,000 并转换为整数
- 现在我可以进行精确的整数计算(仅加法和减法),这意味着结果必须精确(与使用双精度的加法和减法相反)
- 在返回之前,我再次将结果除以 10,000 以转换回双倍
不幸的是,我已经失去了转换的准确性。我的以下测试代码显示了这一点:
double[] examples = {1.3456, 6.0000, 1.9999, 7.0001};
int[] inInt = new int[4];
double[] outDouble = new double[4];
// Input conversion from double to int
for (int i = 0; i < 4; i++) {
inInt[i] = (int) (examples[i] * 10_000);
}
// Integer calculations elided
// Output conversion back to double
for (int i = 0; i < 4; i++) {
outDouble[i] = ((double) inInt[i] / 10_000.0);
}
// Show
System.out.println(Arrays.toString(examples));
System.out.println(Arrays.toString(inInt));
System.out.println(Arrays.toString(outDouble));
上面的代码给了我
[1.3456, 6.0, 1.9999, 7.0001]
[13455, 60000, 19999, 70001]
[1.3455, 6.0, 1.9999, 7.0001]
因此,您可以看到,虽然第 2 个到第 4 个示例有效,但转换为 int 时丢失了精度,因为它变成了 而不是 .1.3456
13455
13456
是否有可能完全消除这里的精度损失?
我只看到一个选项:double >字符串>整数>运算,使用整数>构造字符串>构建 double,但这非常费力。我正在使用 Java,但我认为这在这里并不重要。
PS 这里
所说的“精度损失”是指由于传入数据的双重性质而导致的任何精度损失,即对我来说,“没有精度损失”的计算是对整数进行的计算,整数是从传入数据构建的。
答:
0赞
Eritrean
3/16/2023
#1
使用引用而不是基元进行输入,并转换为 为了准确起见。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));
}
评论
1赞
Eric Postpischil
3/16/2023
没有解释的代码不是一个好的答案。代码的工作方式很重要。详细地说,代码的作用很重要。概念很重要。为什么以前的代码不起作用很重要。为什么新代码有效很重要。
评论
double
double
double
BigDecimal
double
BigDecimal