下一轮浮点舍入

时间:2017-02-12 20:25:09

标签: java floating-point decimal rounding

此问题与this one和其他许多问题有关,但不是重复。我使用double s,这肯定是正确的说小数点后6位并使用

String.format("%f.6", x)

始终返回正确的值。然而,

String.valueOf(x)

没有。我需要“舍入”x,以便它生成相同的(或者在尾随零的情况下更短)结果为格式化为6位小数。 我不想要十进制数的确切表示,我知道它不存在。使用

x = Double.parseDouble(String.format("%.6f", x))

给了我想要的东西,但我正在寻找一些更直接的方法(更快,不产生垃圾)。四舍五入的明显方法

x = 1e-6 * Math.round(1e6 * x)

工作。

作为示例,请考虑以下剪切

double wanted = 0.07;
double given = 0.07000000455421122;
double wrong = 1e-6 * Math.round(1e6 * given);
double slow = Double.parseDouble(String.format("%.6f", given));
double diff = wrong - wanted;
double ulp = Math.ulp(wrong);

计算这些值

wanted 0.07
given 0.07000000455421122
wrong 0.06999999999999999
slow 0.07
diff -1.3877787807814457E-17
ulp 1.3877787807814457E-17

问题似乎是1e-6 * 70000产生了最好的结果,但距离我想要的距离只有一个。

再一次:我不是要问如何回合,我问的是如何更快地做到这一点。所以我担心,BigDecimal不是可行的方式。

1 个答案:

答案 0 :(得分:3)

问题是1e-6不完全是10 -6 (实际上是0.000000999999999999999954748111825886258685613938723690807819366455078125)

除了乘以这个,你应该除以1e6,恰好是10 6 ,然后结果将是最接近0.07的浮点数({{1} }或0.070000000000000006661338147750939242541790008544921875)。