2017-02-12 129 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