從java中來說:2減1.1等於幾?

2020-12-11 煙竹先生

在Java中有一個奇怪的現象,我們編寫代碼2-1.1,原本以為結果是非常明顯的0.9,但答案卻讓人大吃一驚,如圖:

原因在於:Java基本數據類型中的float、double類型的實質是浮點數,浮點數不能存儲精確的數據,這樣的話,浮點數在進行計算的時候,計算結果就不是精確的值。所以這裡得出經驗,在實際開發中,我們在對數值進行計算的時候,應儘量避免使用Java的+ - * / 等運算符,因為容易出現損失精度的問題,導致最終的計算結果錯誤。

尤其是在電商平臺中都是杜絕使用此種計算方式的,因為由於這種計算導致金額出現的誤差,所帶來的損失是無法估量的,也許就因為差一分錢,導致報表計算錯誤,客戶帳單對不上,都會帶來大麻煩。所以我們有必要找到一種正確的計算方法。

Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數進行精確的運算。雙精度浮點型變量double可以處理16位有效數。在實際應用中,需要對更大或者更小的數進行運算和處理。float和double只能用來做科學計算或者是工程計算,在商業計算中要用java.math.BigDecimal。BigDecimal所創建的是對象,我們不能使用傳統的+、-、*、/等算術運算符直接對其對象進行數學運算,而必須調用其相對應的方法。

1、加法

2、減法

3、乘法

在上述的截圖中,會發現我們在做運算之前,都會將double值轉化為String值,儘管BigDecimal提供了多種構造方法,也是支持傳入double值的,但這裡我們並不推薦。因為傳入double值是容易出問題的,如圖:

a)參數類型為double的構造方法的結果有一定的不可預知性。有人可能認為在Java中寫入newBigDecimal(0.1)所創建的BigDecimal正好等於 0.1(非標度值 1,其標度為 1),但是它實際上等於0.1000000000000000055511151231257827021181583404541015625。這是因為0.1無法準確地表示為 double(或者說對於該情況,不能表示為任何有限長度的二進位小數)。這樣,傳入到構造方法的值不會正好等於 0.1(雖然表面上等於該值)。

b)另一方面,String 構造方法是完全可預知的:寫入 newBigDecimal("0.1") 將創建一個 BigDecimal,它正好等於預期的 0.1。因此,比較而言,通常建議優先使用String構造方法。

c)當double必須用作BigDecimal的源時,請注意,此構造方法提供了一個準確轉換;它不提供與以下操作相同的結果:先使用

Double.toString(double)

方法,然後使用

BigDecimal(String)

構造方法。將double轉換為String,也可以使用String的static方法:String.

valueOf(double)

4、除法

在使用除法時,我們發現divide方法中,我們多傳入了幾個參數。如果對於可以除盡的數不傳入這兩個參數也是沒有問題的,但如果我們使用100除以3會出現什麼問題呢?

我們發現報錯了,原因在於:通過BigDecimal的divide方法進行除法時當不整除,出現無限循環小數時,就會拋異常:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. 所以不管能不能除盡,我們都要防患於未然告訴運算器我們除不盡的方案是什麼。

BigDecimal已經幫助我們定義好了捨入模式,只有在作除法運算或四捨五入時才用到捨入模式。如下圖:

這麼多的四捨五入模式,我們在實際開發中應該使用那種呢,這個還是要分情況的。我倒是建議使用UNNECESSARY這種模式:計算結果是精確的,不需要四捨五入,那你可能會說這樣不就有問題了嗎?別著急,待計算完成後我們再單獨對結果進行四捨五入?為什麼要這樣呢?因為我們不能保證我們的程序中只存在一次計算,如果我們有一個公式要連續對數值進行乘法和除法,每次都四捨五入,那計算結果才會有問題,但如果我們只對最終的結果值四捨五入就沒有問題了,因為多數在保存的時候,資料庫都要求保留兩位小數。首先我們來看下不同的模式下計算的結果值有什麼差異?

在UNNECESSARY的時候最為精確。因為其保留的小數也最多。具體我們可以打開原始碼自己看下原因。那最終我們如何將數值保留兩位小數呢?

當然,我的這個經驗我也不能百分百是完全正確的,只是說在我的日常工作中的確這麼做的,如果各位有不同的意見請儘快告訴我。

推薦一下我的java免費資料分享群:614181335,裡面都是學習java的,如果你正在學習,小編歡迎你加入,不定期分享乾貨,包括視頻源碼等,歡迎初學和進階中的小夥伴

相關焦點

  • 面試官:減2等於13,減3等於20,減2再減3等於10,這個數是多少?
    最近,有讀者和老羊交流到一個有趣的面試問題:減2等於13,減3等於20,減2再減3等於10,這個數是多少?對,這就是一個非常簡單的數學題目,畢竟題目越精簡,就越能夠考驗人的大腦的反應速度,而且由於面試的是極度需要臨場反應能力的崗位,所以,面試官留出了2分鐘的時間來讓面試者做準備,畢竟這個題目從一般的角度來看,沒有解題之法,只能先研究一番,再嘗試得出答案!
  • 老師,一減二分之一等於幾?
    我在想,我是什麼時候知道一減二分一等於幾的,好像真的忘記了。   對於一減二分之一等於幾,到底屬於知識範疇還是常識範疇現在已經不重要了,重要的是為什麼他不知道一減二分之一等於幾?  首先我有幾個疑問:1、他高中數學老師知道他不知道一減二分之一等於幾嗎?假如知道,為什麼不告訴他呢, 假如不知道,是不是高中數學老師的失職呢?
  • java之小小的基礎知識點
    一.如何編寫java程序呢?1.新建一個java工程2.新建一個包名 新建一個java類 包的命民 :域名的反向 www.百度.com com.百度.www3.編寫內容4.在類中的空白處 右擊運行java 選擇run as java application詳情請參考:
  • 跟我學java編程—Java表達式
    在Java語言中,表達式是由變量或常量與符號的組合,例如:num1+num2或age>18等。表達式中常用的符號稱為運算符,這些運算符作用的變量或常量稱為操作數。例如:在表達式age>18中,age和18是操作數,符號>為運算符。同樣,在表達式num1+num2中,num1和num2均為操作數,符號+為算術運算符。
  • 7分之3減7分之3等於 七分之三減七分之三等於幾分之幾
    7分之3減7分之3等於  7分之3減7分之3等於0。分數減法是分數的基本運算之一,根據分數減法的運算法則可知,同分母分數相減,分母不變,分子相減所得的差作為差的分子;因此分母7不變,分子3與3相減,得0,因此7分之3減7分之3等於0。
  • 麥子java黑馬程式設計師前輩之路入門基礎java數組折半查找案例例題
    在了解java數組排序功能塊代碼的操作後下面咱們再來分享下關於給定一個元素,然後在數組中查找元素是否存在,如果存在則輸出對應數組元素下的角標,如果不存在則輸出-1;java在數組中查找某一個元素案例上圖所示,在給定的數組裡查找對應元素的角標位置數,上圖是查找存在的元素位置,如過查找的元素不存在數組裡頭編譯會如何?
  • 幼兒英語笑話:四減四等於幾(帶翻譯)
    新東方網>英語>英語學習>少兒英語>英語故事>正文幼兒英語笑話:四減四等於幾(帶翻譯) 2013-02-03 11:27 來源:網絡 作者:
  • 趣味雙語故事 | 6減6等於幾?
    &34;Sorry, teacher, I… I don&34;一天,他的老師問:「彼得,6減去6等於幾?」 「 對不起,老師,我,我不知道。」One day 一天how much 多少six minus six 6減去6minus [ˈmaɪnəs] prep.
  • Java的四則運算符與取模運算符
    大家都知道,四則運算符主要有,加,減,乘,除這四種,那麼這是種運算符是如何在java程序中運用的呢?在java程序中加(+),減(-),乘(*),除(/),取模(%).小括號裡裡面的符號就是java程序中的表示符號,大家注意一下*,/,%三個運算符。
  • 跟我學java編程—Java算術運算符
    算術運算符用在算術表達式中,其作用和數學中的運算符相同,下表列出了Java語言支持的算術運算符。示例1:加減乘除操作符運算在D盤Java目錄下,新建「OperationSample.java」文件。圖 6-2 算術運算符示例運行結果從上述結果可以看出,Java語言中的加、減、乘、除運算同數學中的運算是一致的。
  • Java編程中常見的異常
    數組的初始化是對數組分配需要的空間,而初始化後的數組,其中的元素並沒有實例化,依然是空的,所以還需要對每個元素都進行初始化(如果要調用的話)2.java.lang.classnotfoundexception    這個異常是很多原本在jb等開發環境中開發的程式設計師,把jb下的程序包放在wtk下編譯經常出現的問題,異常的解釋是
  • Java開發中synchronized的定義及用法
    synchronizedsynchronized是java中用於同步的關鍵字,其典型的作用域如下所示.synchronized大括號包裹的代碼同步執行.synchronized作用的對象為SynchronizedExample1的對象實例,例如main函數中的example1以及example2.
  • 【答疑解惑】Java中的高精度數字
    就像使用基本數據類型那樣,答案是不能。Java中的基本數據類型有的時候是不能滿足實際編程需要的,特別是在數學、科學、工程、貨幣等領域,因為精度不夠,所以Java提供了java.math.BinInteger類和java.math.BigDecimal類,其中BigInteger類是針對大整數的處理類,而BigDecimal類則是針對大小數的處理類,它們不屬於基本數據類型,所以不能按照普通的基本數據類型那樣計算,那麼它們是怎樣進行數據運算的呢
  • 最全的Java 運算符教程筆記
    我們可以把運算符分成以下幾組:算術運算符關係運算符位運算符邏輯運算符賦值運算符其他運算符算術運算符算術運算符用在數學表達式中,它們的作用和在數學中的作用一樣。下表列出了所有的算術運算符。表格中的實例假設整數變量A的值為10,變量B的值為20:操作符 描述 例子 + 加法 - 相加運算符兩側的值 A + B 等於 30 - 減法 - 左操作數減去右操作數 A – B 等於 -10 * 乘法 - 相乘操作符兩側的值 A * B等於200 / 除法 - 左操作數除以右操作數 B /
  • java常用幾大類庫
    java.lang下的類不需要導包,其他需要。 看類的解釋和說明。 學習構造方法。 使用成員方法。第2章 Scanner類了解了API的使用方式,我們通過Scanner類,熟悉一下查詢API,並使用類的步驟。2.1 什麼是Scanner類一個可以解析基本類型和字符串的簡單文本掃描器。
  • 詳解Java表達式與運算符
    例如,表達式num1+num2,其操作數是num1和num2,運算符是」+」。在java語言中,運算符可分為5種類型:算術運算符、賦值運算符、關係運算符、邏輯運算符、位運算符。根據操作數的不同,運算符又分為單目運算符、雙目運算符和三目運算符。單目運算符只有一個操作數,雙目運算符有兩個操作數,三目運算符則有三個操作數。
  • 淺談Java中的幾種隨機數
    最明顯的,也是直觀的方式,在Java中生成隨機數隻要簡單的調用:java.lang.Math.random() 在所有其他語言中,生成隨機數就像是使用Math工具類,如abs, pow, floor, sqrt和其他數學函數。
  • Java中日期的幾種常見操作 ―― 取值、轉換、加減、比較
    日期取值 在舊版本 JDK 的時代,有不少代碼中日期取值利用了 java.util.Date 類,但是由於 Date 類不便於實現國際化,其實從 JDK1.1 開始,就更推薦使用 java.util.Calendar 類進行時間和日期方面的處理。這裡便不介紹 Date 類的操作,讓我們直奔主題吧,如何利用 Calendar 類取得現在的日期時間。
  • Java 中 Comparable 和 Comparator 比較
    此外,「實現Comparable接口的類的對象」可以用作「有序映射(如TreeMap)」中的鍵或「有序集合(TreeSet)」中的元素,而不需要指定比較器。Comparator 定義Comparator 接口僅僅只包括兩個個函數,它的定義如下:package java.util; public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); }(01) 若一個類要實現Comparator
  • 幾種任務調度的 Java 實現方法與比較
    package com.ibm.scheduler;import java.util.Calendar;import java.util.Date;import java.util.TimerTask;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService