2017-02-12 98 views
1

这个问题与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产生最好的结果,但它是一个ULP远离我想要的是。

再一次:我不是问如何轮回,我问如何更快地做到这一点。所以我很害怕,BigDecimal不是要走的路。

+1

对不起,但鉴于'BigDecimal'有一个方法可以完全符合你的要求,我不明白为什么这个选项不在桌面上。 –

+0

'double'不能准确地代表'0.07'。你可以“达到”的最好方法是“0.070000000000000007”,为此你可以简单地做'double wanted = int(给定* 100)/ 100.0'。 –

+0

@JoeC速度(和生产的垃圾)。这在我的真实用例中并不重要,但我很好奇。 – maaartinus

回答

3

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

而是通过这个相乘的,你应该1e6划分而这正是10 ,那么结果将是最接近0.07的浮点数(这是0.07或0.070000000000000006661338147750939242541790008544921875)。

+0

哇!真的很简单吗? – maaartinus