[英]Using Java Double.toString() style formatting with more digits (DecimalFormat does not work with low precision numbers)
核心問題是我需要記錄一系列雙打,每個雙打都有不同數量的有效數字。 數字的變化有很大的數字。 一些有0(例如5257),有些有2(例如1308.75),有些一直有7(例如124.1171875)。 基本上是小數點后0到7位有效數字之間的所有內容。
標准Double.toString()適用於所有內容,但有7位有效數字。 這是一直到6位數字,有效數字都打印沒有任何無關緊要的數字。 但是對於那些有7位有效數字的人,toString()會將最后一位數字舍入。 即
5257 -> "5257"
1308.75 -> "1308.75"
124.1171875 -> "124.117188"
當然我嘗試使用DecimalFormat(“#。#######”),這解決了丟失有效數字的問題,但它為許多低精度雙精度打印了無關緊要的數字。 即
1308.75 -> "1308.7499998"
這也是不可接受的,因為它浪費了大量的空間(通常每天記錄> 2 GB的數據)和2)它使用日志弄亂了應用程序。
在識別有效數字時,與toString()相比,DecimalFormat似乎很糟糕,無論如何要修復它? 我只想使用toString()樣式處理有效數字,並將最大位數從6擴展到7。
有任何想法嗎? 謝謝
如果你擔心完全保留十進制值,你應該使用BigDecimal
開始 - double
從根本上說是不合適的,作為二進制浮點類型。
碰巧的是,我無法在DecimalFormat
重現你1308.75的行為,這並不讓我感到驚訝,因為這個值可以完全表示為double
。 事實上,無論如何, DecimalFormat
似乎應用了一些啟發式算法,因為即使1308.76也是1308.76 - 這讓我感到驚訝, 實際值是1308.759999999999990905052982270717620849609375。 它意味着,如果你在代碼中使用1308.7599999999999,它會出來為1308.76,因為它是完全一樣的價值盡可能double
關注。 如果你需要區分這兩個值,你肯定應該使用BigDecimal
。
另請注意,1308.75有6 位有效數字 - 它有2 位小數 。 值得注意區分這兩個概念。
在我看來有點奇怪,這就是我出去測試的原因。 我試過這段代碼:
public class MySimpleTest
{
public static void main(String args[])
{
format(5257);
format(1308.75);
format(124.1171875);
}
private static void format(double d)
{
DecimalFormat df = new DecimalFormat("##.#######");
System.out.println("" + d + " -> " + df.format(d));
}
}
它給了我這個結果:
5257.0 -> 5257
1308.75 -> 1308.75
124.1171875 -> 124.1171875
您可能正在測試“##。######”(點后只有6#),或者您的號碼可能有尾隨數字。 重點是##。#######和##。0000000格式將圍繞最后一個小數點(例如,格式化之前124.11718755將四舍五入為124.1171876)。 如果你想要它被截斷,首先嘗試截斷它,做這樣的事情:
double d = 124.1171875999999;
org.apache.commons.math.util.MathUtils.round(d, 6, java.math.BigDecimal.ROUND_DOWN);
DecimalFormat df = new DecimalFormat("##.#######");
System.out.println("" + d + " -> " + df.format(d));
除了Jon Skeet所提到的,為什么不保留一個DecimalFormat數組,每個數組都包含多個數字?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.