日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

为什么在Java 6上Math.round(0.499999999999999917)舍入为1

發布時間:2023/12/3 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为什么在Java 6上Math.round(0.499999999999999917)舍入为1 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

總覽

錯誤表示錯誤和算術舍入錯誤有兩種類型,它們在浮點計算中很常見。 在此簡單示例中,這兩個錯誤組合在一起,在Java 6中Math.round(0.4999999999999999999917)舍入為1。

表示錯誤

浮點數是以2為底的格式,表示所有數字都表示為2的冪的和。例如6.25是2 ^ 2 + 2 ^ 1 + 2 ^ -2。 但是,即使像0.1這樣的簡單數字也無法準確表示。 轉換為BigDecimal時,這一點變得很明顯,因為它將保留實際表示的值而無需取整。

new BigDecimal(0.1)= 0.1000000000000000055511151231257827021181583404541015625 BigDecimal.valueOf(0.1)= 0.1

使用構造函數獲取實際表示的值,使用valueOf給出與打印雙 精度字相同的舍入值

解析數字時,會將其舍入為最接近的表示值。 這意味著存在一個略小于0.5的數字,由于它是最接近的表示值,因此將四舍五入為0.5。

下面用蠻力搜索舍入為1.0的最小值

public static final BigDecimal TWO = BigDecimal.valueOf(2);public static void main(String... args) {int digits = 80;BigDecimal low = BigDecimal.ZERO;BigDecimal high = BigDecimal.ONE;for (int i = 0; i <= 10 * digits / 3; i++) {BigDecimal mid = low.add(high).divide(TWO, digits, RoundingMode.HALF_UP);if (mid.equals(low) || mid.equals(high))break;if (Math.round(Double.parseDouble(mid.toString())) > 0)high = mid;elselow = mid;}System.out.println("Math.round(" + low + ") is " + Math.round(Double.parseDouble(low.toString())));System.out.println("Math.round(" + high + ") is " + Math.round(Double.parseDouble(high.toString()))); }

源代碼

在Java 7上,您得到以下結果。

Math.round(0.49999999999999997224442438437108648940920829772949218749999999999999999999999999) is 0 Math.round(0.49999999999999997224442438437108648940920829772949218750000000000000000000000000) is 1

令人驚訝的是,在Java 6中,您獲得了關注。

Math.round(0.49999999999999991673327315311325946822762489318847656250000000000000000000000000) is 0 Math.round(0.49999999999999991673327315311325946822762489318847656250000000000000000000000001) is 1

這些數字從何而來?

Java 7值是0.5和前一個表示值之間的中點。 高于此中點時,解析時該值將舍入為0.5。

Java 6值是0.5之前的值與其之前的值之間的中點。

Value 0.5 is 0.5 The previous value is 0.499999999999999944488848768742172978818416595458984375 ... and the previous is 0.49999999999999988897769753748434595763683319091796875The mid point between 0.5and 0.499999999999999944488848768742172978818416595458984375is 0.4999999999999999722444243843710864894092082977294921875... and the mid point between 0.499999999999999944488848768742172978818416595458984375and 0.49999999999999988897769753748434595763683319091796875is 0.4999999999999999167332731531132594682276248931884765625

為什么Java 6的值更小

在Java 6 Javadoc中, Math.round(double)被定義為

(long)Math.floor(a + 0.5d)

此定義的問題在于0.49999999999999994 + 0.5的舍入誤差為1.0。

在Java 7 Javadoc Math.round(double)中,它僅聲明:

返回最接近參數的長整數,并舍入四舍五入。

那么Java 7如何解決這個問題?

Java 7的Math.round的源代碼如下所示

public static long round(double a) {if (a != 0x1.fffffffffffffp-2) // greatest double value less than 0.5return (long)floor(a + 0.5d);elsereturn 0; }

最大值小于0.5的結果將進行硬編碼。

那么0x1.fffffffffffffp-2是什么呢?

它是浮點值的十六進制表示。 它很少使用,但是它很精確,因為所有值都可以無錯誤地表示(最多53位)。

相關鏈接

錯誤ID:6430675 Math.round對于0x1.fffffffffffffpp-2具有令人驚訝的行為
為什么Math.round(0.49999999999999994)返回1

參考: 為什么在Java 6上 ,我們的JCG合作伙伴 Peter Lawrey在Vanilla Java博客上將Math.round(0.499999999999999917)舍入為1 。


翻譯自: https://www.javacodegeeks.com/2012/04/why-mathround0499999999999999917-rounds.html

總結

以上是生活随笔為你收集整理的为什么在Java 6上Math.round(0.499999999999999917)舍入为1的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。