一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - JAVA浮點數(shù)計算精度損失底層原理與解決方案

JAVA浮點數(shù)計算精度損失底層原理與解決方案

2020-08-10 19:22星火燎原智勇 Java教程

本文主要介紹了JAVA浮點數(shù)計算精度損失底層原理與解決方案。具有很好的參考價值,下面跟著小編一起來看下吧

問題:

對兩個double類型的值進行運算,有時會出現(xiàn)結(jié)果值異常的問題。比如:

?
1
2
3
4
System.out.println(19.99+20);
System.out.println(1.0-0.66);
System.out.println(0.033*100);
System.out.println(12.3/100);

輸出:

?
1
2
3
4
39.989999999999995
0.33999999999999997
3.3000000000000003
0.12300000000000001

Java中的簡單浮點數(shù)類型float和double不能夠精確運算。這個問題其實不是JAVA的bug,因為計算機本身是二進制的,而浮點數(shù)實際上只是個近似值,所以從二進制轉(zhuǎn)化為十進制浮點數(shù)時,精度容易丟失,導(dǎo)致精度下降。

關(guān)于精度損失的原理可以很簡單的講,首先一個正整數(shù)在計算機中表示使用01010形式表示的,浮點數(shù)也不例外。

比如11,11除以2等于5余1

       5除以2等于2余1

       2除以2等于1余0

       1除以2等于0余1

所以11二進制表示為:1011.

double類型占8個字節(jié),64位,第1位為符號位,后面11位是指數(shù)部分,剩余部分是有效數(shù)字。

正整數(shù)除以2肯定會有個盡頭的,之后二進制還原成十進制只需要乘以2即可。

舉個例子:0.99用的有效數(shù)字部分,

       0.99 * 2 = 1+0.98 --> 1
       0.98 * 2 = 1+0.96 --> 1
       0.96 * 2 = 1+0.92 -- >1
       0.92 * 2 = 1+0.84 -- >1
         ...............

這樣周而復(fù)始是沒法有盡頭的,而double有效數(shù)字有限,所以必定會有損失,所以二進制無法準確表示0.99,就像十進制無法準確表示1/3一樣。

解決辦法:

在《Effective Java》中提到一個原則,那就是float和double只能用來作科學(xué)計算或者是工程計算,但在商業(yè)計算中我們要用java.math.BigDecimal,通過使用BigDecimal類可以解決上述問題,首先需要注意的是,直接使用字符串來構(gòu)造BigDecimal是絕對沒有精度損失的,如果用double或者把double轉(zhuǎn)化成string來構(gòu)造BigDecimal依然會有精度損失,所以我覺得這種解決方法就是在使用中就把浮點數(shù)用string來表示存放,涉及到運算直接用string構(gòu)造double,否則肯定會有精度損失。

1. 相加

?
1
2
3
4
5
6
7
8
9
10
11
/**
 * 相加
 * @param double1
 * @param double2
 * @return
 */
public static double add(String doubleValA, String doubleValB) {
  BigDecimal a2 = new BigDecimal(doubleValA);
  BigDecimal b2 = new BigDecimal(doubleValB);
  return a2.add(b2).doubleValue();
}

2. 相減

?
1
2
3
4
5
6
7
8
9
10
11
/**
 * 相減
 * @param double1
 * @param double2
 * @return
 */
public static double sub(String doubleValA, String doubleValB) {
  BigDecimal a2 = new BigDecimal(doubleValA);
  BigDecimal b2 = new BigDecimal(doubleValB);
  return a2.subtract(b2).doubleValue();
}

3. 相乘

?
1
2
3
4
5
6
7
8
9
10
11
/**
 * 相乘
 * @param double1
 * @param double2
 * @return
 */
public static double mul(String doubleValA, String doubleValB) {
  BigDecimal a2 = new BigDecimal(doubleValA);
  BigDecimal b2 = new BigDecimal(doubleValB);
  return a2.multiply(b2).doubleValue();
}

4. 相除

?
1
2
3
4
5
6
7
8
9
10
11
12
/**
 * 相除
 * @param double1
 * @param double2
 * @param scale 除不盡時指定精度
 * @return
 */
public static double div(String doubleValA, String doubleValB, int scale) {
  BigDecimal a2 = new BigDecimal(doubleValA);
  BigDecimal b2 = new BigDecimal(doubleValB);
  return a2.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}

5. 主函數(shù)調(diào)用

?
1
2
3
4
5
6
7
8
public static void main(String[] args) {
  String doubleValA = "3.14159267";
  String doubleValB = "2.358";
  System.out.println("add:" + add(doubleValA, doubleValB));
  System.out.println("sub:" + sub(doubleValA, doubleValB));
  System.out.println("mul:" + mul(doubleValA, doubleValB));
  System.out.println("div:" + div(doubleValA, doubleValB, 8));
}

結(jié)果展示如下所示:

?
1
2
3
4
add:5.49959267
sub:0.78359267
mul:7.40787551586
div:1.33231241

所以最好的方法是完全拋棄double,用string和java.math.BigDecimal。

java遵照IEEE制定的浮點數(shù)表示法來進行float,double運算。這種結(jié)構(gòu)是一種科學(xué)計數(shù)法,用符號、指數(shù)和尾數(shù)來表示,底數(shù)定為2——即把一個浮點數(shù)表示為尾數(shù)乘以2的指數(shù)次方再添上符號。具體底層如何存儲以及如何進行運行請繼續(xù)關(guān)注我的博客,后續(xù)我會將詳情總結(jié)好的。

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持服務(wù)器之家!

原文鏈接:http://www.cnblogs.com/liang1101/p/6392179.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 美女无内裤下部黄 | 男女发生性关系视频 | 国产成人精品在线 | 九九在线精品亚洲国产 | 国产尤物精品视频 | 国产亚洲精品激情一区二区三区 | 欧美性bbbbbxxxxxxx | 国产绳艺在线播放 | 成年看片免费高清观看 | 欧美贵妇videos办公室 | 成人免费观看一区二区 | aaa毛片在线 | 国产1区二区 | 极品美女穴 | 国产一区二区三区久久精品 | 成人一区二区免费中文字幕 | 手机av| 免费看男女污污完整版 | 欧美国产日韩综合 | 无码国产成人777爽死 | 久久er国产精品免费观看2 | 狐媚小说 | 香蕉国产人午夜视频在线观看 | 国产成人免费片在线视频观看 | 好湿好紧太硬了我太爽了h 好湿好滑好硬好爽好深视频 | 97青草| 国产区香蕉精品系列在线观看不卡 | 亚洲精品一区二区三区在线看 | 欧美又大又粗又爽视频 | ipx 在线播放 | 亚洲国产精品一区二区三区久久 | 国产成人免费高清激情视频 | 国产亚洲玖玖玖在线观看 | 好爽视频 | 国产久草在线 | 日韩手机在线视频 | 国产午夜视频在线观看网站 | 欧美色精品天天在线观看视频 | 国产中文视频 | 狠狠的撞进去嗯啊h女强男视频 | 成人免费视频大全 |