本文目錄一覽:
java 浮點數為什麼精度會丟失
並不是java的浮點數精度會丟失,而是所有用二進位存儲中的浮點數都可能會精度丟失(部分特殊的小數數值可以精確表示),所以計算機中存儲的浮點數都存在精度丟失的風險,不過一邊這個丟失的精度對我們正常的使用不會構成影響。
小數在轉換為二進位時並不一定能用一個精確的二進位表示,大多數時候都是取的一個近似值,這就造成了精度的丟失。如果再用這個二進位進行計算,明顯計算結果的精度會進一步丟失。
舉個簡單的例子把0.1用二進位表示(小數與二進位轉換方法)
(1) 0.1 x 2 = 0.2 取整數位 0 得 0.0
(2) 0.2 x 2 = 0.4 取整數位 0 得 0.00
(3) 0.4 x 2 = 0.8 取整數位 0 得 0.000
(4) 0.8 x 2 = 1.6 取整數位 1 得 0.0001
(5) 0.6 x 2 = 0.2 取整數位 1 得 0.00011
(6) 0.2 x 2 = 0.4 取整數位 0 得 0.000110
(7) 0.4 x 2 = 0.8 取整數位 0 得 0.0001100
(8) 0.8 x 2 = 1.6 取整數位 1 得 0.00011001
(9) 0.6 x 2 = 1.2 取整數位 1 得 0.000110011
(n) …
得到一個無限循環的二進位小數 0.000110011…,沒辦法用一個精確的二進位表示0.1。而且計算機中存儲一個浮點數所用的位數也是有限的,所以只能選擇在某一個精度進行保存。
當然也有特殊的小數,比如0.25的二進位為0.01
附:代碼之謎(五)- 浮點數(誰偷了你的精度?)
關於java單精度與雙精度的問題
單精度和雙精度的區別就是,雙精度要比單精度所存儲的位數要多,至於說3.14師雙精度,是因為Java中,默認的小數都是double類型,也就算雙精度的,如果要定義單精度的話,那就要在小數的後面加上一個f或者F,即 double d = 3.14; float f = 3.14f; 一定要注意後面有沒有「f」和「F」啊,這個初學的時候,經常會考到。樓上說的,是對,但是,他那樣寫,就一定會報錯。記住,單精度的變數定義,一定要在值的後面加上標識。
Java語言中的浮點型數據的float和double的單精度和雙精度到底是啥意思?
主要有下面幾個區別,手冊上的,希望能幫到你
1、變數類型不同
float屬於單精度型浮點數據。
double屬於雙精度型浮點數據。
2、指數範圍不同
float的指數範圍為-127~128。
double而double的指數範圍為-1023~1024
3、表達式指數位不同
float的表達式為1bit(符號位)+8bits(指數位)+23bits(尾數位)
double的表達式為1bit(符號位)+ 11bits(指數位)+ 52bits(尾數位)
4、佔用內存空間不同
float佔4個位元組(32位)內存空間,其數值範圍為3.4E-38~3.4E+38。
double佔8 個位元組(64位)內存空間,其數值範圍為1.7E-308~1.7E+308。
5、有效位數不同
float只能提供七位有效數字。
double可提供16位有效數字。
怎麼控制精度在java
JAVA中如何對double或者float的浮點數進行精度計算,在JAVA中提供了多種參數來實現精度的不同控制方式。具體例子如下:
轉自
Java代碼
/*
* Created on 2005-6-5
* Author stephen
* Email zhoujianqiang AT gmail DOT com
* CopyRight(C)2005-2008 , All rights reserved.
*/
package com.soft4j.utility;
import java.math.BigDecimal;
/**
* 與小數位精度(四捨五入等)相關的一些常用工具方法.
*
* float/double的精度取值方式分為以下幾種: br
* java.math.BigDecimal.ROUND_UP br
* java.math.BigDecimal.ROUND_DOWN br
* java.math.BigDecimal.ROUND_CEILING br
* java.math.BigDecimal.ROUND_FLOOR br
* java.math.BigDecimal.ROUND_HALF_UPbr
* java.math.BigDecimal.ROUND_HALF_DOWN br
* java.math.BigDecimal.ROUND_HALF_EVEN br
*
* @author stephen
* @version 1.0.0
*/
public final class RoundTool {
/**
* 對double數據進行取精度.
* p
* For example: br
* double value = 100.345678; br
* double ret = round(value,4,BigDecimal.ROUND_HALF_UP); br
* ret為100.3457 br
*
* @param value
* double數據.
* @param scale
* 精度位數(保留的小數位數).
* @param roundingMode
* 精度取值方式.
* @return 精度計算後的數據.
*/
public static double round(double value, int scale, int roundingMode) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(scale, roundingMode);
double d = bd.doubleValue();
bd = null;
return d;
}
/**
* 測試用的main方法.
*
* @param argc
* 運行參數.
*/
public static void main(String[] argc) {
//下面都以保留2位小數為例
//ROUND_UP
//只要第2位後面存在大於0的小數,則第2位就+1
System.out.println(round(12.3401,2,BigDecimal.ROUND_UP));//12.35
System.out.println(round(-12.3401,2,BigDecimal.ROUND_UP));//-12.35
//ROUND_DOWN
//與ROUND_UP相反
//直接捨棄第2位後面的所有小數
System.out.println(round(12.349,2,BigDecimal.ROUND_DOWN));//12.34
System.out.println(round(-12.349,2,BigDecimal.ROUND_DOWN));//-12.34
//ROUND_CEILING
//如果數字0 則和ROUND_UP作用一樣
//如果數字0 則和ROUND_DOWN作用一樣
System.out.println(round(12.3401,2,BigDecimal.ROUND_CEILING));//12.35
System.out.println(round(-12.349,2,BigDecimal.ROUND_CEILING));//-12.34
//ROUND_FLOOR
//如果數字0 則和ROUND_DOWN作用一樣
//如果數字0 則和ROUND_UP作用一樣
System.out.println(round(12.349,2,BigDecimal.ROUND_FLOOR));//12.34
System.out.println(round(-12.3401,2,BigDecimal.ROUND_FLOOR));//-12.35
//ROUND_HALF_UP [這種方法最常用]
//如果第3位數字=5,則第2位數字+1
//備註:只看第3位數字的值,不會考慮第3位之後的小數的
System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_UP));//12.35
System.out.println(round(12.3449,2,BigDecimal.ROUND_HALF_UP));//12.34
System.out.println(round(-12.345,2,BigDecimal.ROUND_HALF_UP));//-12.35
System.out.println(round(-12.3449,2,BigDecimal.ROUND_HALF_UP));//-12.34
//ROUND_HALF_DOWN
//如果第3位數字=5,則做ROUND_UP
//如果第3位數字5,則做ROUND_DOWN
System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_DOWN));//12.35
System.out.println(round(12.3449,2,BigDecimal.ROUND_HALF_DOWN));//12.34
System.out.println(round(-12.345,2,BigDecimal.ROUND_HALF_DOWN));//-12.35
System.out.println(round(-12.3449,2,BigDecimal.ROUND_HALF_DOWN));//-12.34
//ROUND_HALF_EVEN
//如果第3位是偶數,則做ROUND_HALF_DOWN
//如果第3位是奇數,則做ROUND_HALF_UP
System.out.println(round(12.346,2,BigDecimal.ROUND_HALF_EVEN));//12.35
System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_EVEN));//12.35
}
}
如果要求精確控制位數,推薦使用BigDecimal,這是在JDK1.4版本之後推薦的一個處理精度的類。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/286043.html