簡體   English   中英

使用 Java 以輸入的精度遞增浮點數

[英]Increment floating point numbers with the precision of the input with Java

我正在尋找以自己的精度遞增浮點數的最優化且易於閱讀的版本:

increment(1000) should return 1001
increment(100.1) should return 100.2
increment(0.1) should return 0.2
increment(0.01) should return 0.02
increment(0.001) should return 0.002
increment(0.0009) should return 0.0010
increment(0.000123) should return 0.000124
increment(increment(0.0009)) should return 0.002

它可以通過字符串操作來完成,但我不想將其轉換為字符串並將其解析回雙精度。

我使用字符串操作完成了以下操作:

public static double incrementWithMover(double value){
    DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
    df.setMaximumFractionDigits(340); //340 = DecimalFormat.DOUBLE_FRACTION_DIGITS
    String valueString = df.format(value);
    String[] splitted = valueString.split("\\.");

    StringBuilder mover = new StringBuilder();

    if(splitted.length == 2){ // Floating Decimals
        int precision = splitted[1].length();
        df.setMaximumFractionDigits(precision);
        mover = new StringBuilder("0.");
        for(int i =1; i<precision; i++){
            mover.append("0");
        }

        mover.append("1");
    }
    else{   // Non Floating Decimals
        mover = new StringBuilder("1");
    }


    double incremented = Double.parseDouble(valueString) + Double.parseDouble(mover.toString());
    return Double.parseDouble(df.format(incremented));
}

我正在嘗試編寫此方法,因為我正在檢查不同的值並嘗試將所有值以它們自己的精度遞增一

編寫這種incrementFloating方法的最佳方法是什么?

這可能對你有用。 從雙打改為弦樂。

String[] vals = { "1000","1000.1", ".1", ".01", ".001", ".00123", ".0004" };
for (String v : vals) {
    System.out.printf("%s -> %s%n", v, incrementFloating(v));
}

印刷

1000 -> 1001
1000.1 -> 1000.2
.1 -> 0.2
.01 -> 0.02
.001 -> 0.002
.00123 -> 0.00124
.0004 -> 0.0005

方法聲明


public static String incrementFloating(String v) {  
    BigDecimal b = new BigDecimal(v);
    BigDecimal increment =
            BigDecimal.valueOf(1).scaleByPowerOfTen(-b.scale());
    return b.add(increment).stripTrailingZeros().toString();
}

使用 Java 以輸入的精度遞增浮點數

這不是它的工作原理。

浮點數和雙精度數並不像您顯然認為的那樣存儲。

想象一下整個數軸。 從負無窮到正無窮。

這條線上有無數個 integer 值。 在任何 2 個 integer 值之間,也存在無限數量的值。

電腦不是魔法。 浮點數是 32 位,雙精度數是 64 位。 根據基本數學,32 位最多只能區分 2^32 個數字,即大約 40 億。

40 億是路,遠小於無窮大的 2 個數量級

那么是如何工作的呢? 好吧,大約有 40 億個數字是“祝福”的。 這些數字可以用float表示,其他數字不能 比如 0.3就沒有被祝福 0.3 根本不是浮點數系統中的數字。 它不存在。

那么,我該如何解釋float x = 0.3; 工作,或者當你運行時會發生什么float x = 0.1 + 0.2; ?

好吧,float 和 double 操作會默默地轉換為最近的祝福數字。

祝福數字的分布基於二進制(因此在十進制中它們沒有任何特殊意義),並且分布不均。 例如,在接近 1.0 時,有遠超過接近 100.0 的地方。

這意味着錯誤無處不在 您從根本上描述的操作在這里沒有意義。 你不能用花車或雙打做你想做的事。 時期。

Go 帶字符串,或 go 帶 BigDecimal。

如果您有興趣,這里是 go:

BigDecimal bd = new BigDecimal(0.3);
System.out.println(bd);
> 0.299999999999999988897769753748434595763683319091796875

這不是我編的。 編寫該代碼並運行它。 那個不敬的數字是什么?

這是最接近 0.3 的祝福數字。

So, in double number systems, applying your algorithm, increment(0.3) would try to calculate 0.299999999999999988897769753748434595763683319091796876 , which isn't blessed, and the nearest blessed number to that is simply 0.299999999999999988897769753748434595763683319091796875 again, and the operation would do nothing.

沒有意義。

Strings 或 BigDecimal,這是唯一的方法。 從這個意義上說,window 的效率更高,但除非您打算每秒運行此操作數百萬次,否則您不會注意到。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM