簡體   English   中英

浮點的奇怪行為

[英]Strange behavior of float point

我了解random.Float()帶回介於0.0到0.999之間的浮點數...

但是由於未知的原因,幾乎相同的代碼會帶回2個不同的答案。

我想了解為什么t1可以隨機1.0,而t2不能隨機。

我試圖檢查類似的問題,但找不到類似的問題

    Random rand = new Random();
    for (int i = 0; i < 1000000000; i++) {
        float t1 = 0.9f + rand.nextFloat() * 0.1f;
        float t2 = 0.1f + rand.nextFloat() * 0.9f;
        if (t1 == 1.0f) {
            System.out.println("t1 " + t1);
        }
        if (t2 == 1.0f) {
            System.out.println("t2 " + t2);
        }
    }

沒有錯誤消息,我只是不明白為什么t1有時會帶回1.0號而t2沒有。

編輯:t1生成最大值為0.999 ... * 0.1,即0.0999 ... + 0.9 = 0.9999 ... t2生成最大值為0.999 ... * 0.9,即0.8999 ... + 0.1 = 0.9999 ...兩者都應一樣嗎?

造成這種差異的主要原因是,對於任何x <1,.9 + x •.1大於.1 + x •.9,並且Random.nextFloat返回的值小於1。對於返回的最大值,前者表達式非常接近1以至於將其四舍五入為float會產生1,但后者的表達式離1更遠,而將其四舍五入為float會產生下一個小於1的float

Random.nextFloat返回的Random.nextfloatRandom.nextfloat 16777215/16777216。 M為該最大值,令d = 1 − M = 1/16777216。

如果我們使用實數計算t1 ,則其最大值將為.9 + M •.1。 = .9 +(1- d )•.1 = 1-.1• d 同樣, t2將為.1 + M •.9 = .1 +(1- d )•.9 = 1-.9• d

現在,我們可以很容易地看到,最大的t1 (如果與實數計算)為0.1•d遠離1,但t2有0.9•從1 的路程。

Random.nextFloat返回的最大值是16777215/16777216的原因是它是小於1的最大floatfloat格式的精度是導致可表示的值之間的步長為1/16777216。 這意味着此鄰域中的兩個可表示值分別是16777215/16777216和1, d是它們之間的距離。 上面的計算顯示t1的最大值與t1僅相差0.1• d 。因此,將其四舍五入為float ,1是最近的float

相比之下,最大值t20.9•d離1。這意味着它僅僅是0.1•從一千六百七十七萬七千二百十六分之一千六百七十七萬七千二百十五ð路程。 因此,將其四舍五入為float ,16777215/16777216是最近的float

那就是使用實數算法。 下面,我將展示浮點算法。 它具有舍入誤差,但是事實證明這些誤差足夠小,不會改變結果。

Java ,源文本.1f.9f轉換為float ,其結果為0.100000001490116119384765625和0.89999997615814208984375。 表達式中的算術是使用double執行的,然后將結果舍入為float以分配給t1t2

可以計算出t1的最大值:

  • 替換nextFloat的最大返回值將產生0.9f + 16777215./16777216 * 0.1f;
  • double算術評估得出0.999999971687793642871611154987476766109109466552734375。
  • 轉換為float產生1,因為該double float值介於0.999999940395355355224609375(下一個較低的float值)和1(下一個較高的float值)之間,並且比前者更接近后者。

可以計算出t2的最大值:

  • 用最大的nextFloat返回值替換為0.1f + 16777215./16777216 * 0.9f;
  • double算術評估得出0.99999992400407933246242464520037174224853515625。
  • 轉換為float產生0.999999940395355224609375。

暫無
暫無

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

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