Java保留小數問題

保留兩位小數的幾種方式:java

 

方式一:git

四捨五入 
數據庫

double   f   =   111231.5585; 
BigDecimal   b   =   new   BigDecimal(f); 
double   f1   =   b.setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue();

保留兩位小數 

方式二:app

java.text.DecimalFormat   df   =new   java.text.DecimalFormat("#.00"); 
df.format(你要格式化的數字);less

例:new java.text.DecimalFormat("#.00").format(3.1415926)ide

#.00 表示兩位小數 #.0000四位小數 以此類推...工具

 

方式三:ui

double d = 3.1415926;this

String result = String .format("%.2f");spa

%.2f %. 表示 小數點前任意位數   2 表示兩位小數格式後的結果爲f 表示浮點型

 

方式四:

NumberFormat ddf1=NumberFormat.getNumberInstance() ;

void setMaximumFractionDigits(int digits)
digits 顯示的數字位數
爲格式化對象設定小數點後的顯示的最多位,顯示的最後位是舍入的

import java.text.* ;
import java.math.* ;
class TT{
 public static void main(String args[]){ 
  double x=23.5455;
  NumberFormat ddf1=NumberFormat.getNumberInstance() ;

  ddf1.setMaximumFractionDigits(2);
  String s= ddf1.format(x) ;
  System.out.print(s);
 }
}
  

---------------------------------------------------------------------------------------------------------

 

有一篇:

 

(1)、浮點數精確計算

勝利油田三流合一項目中一直存在一個問題,就是每次報表統計的物資金額和實際的金額要差那麼幾分錢,和實際金額不一致,讓客戶以爲老是不那麼舒服,緣由是由於咱們使用java的浮點類型double來定義物資金額,而且在報表統計中咱們常常要進行一些運算,但Java中浮點數(double、float)的計算是非精確計算,請看下面一個例子:

    System.out.println(0.05 + 0.01);

    System.out.println(1.0 - 0.42);

    System.out.println(4.015 * 100);

    System.out.println(123.3 / 100);

你的指望輸出是什麼?可實際的輸出確實這樣的:

    0.060000000000000005

0.5800000000000001

401.49999999999994

1.2329999999999999

這個問題就很是嚴重了,若是你有123.3元要購買商品,而計算機卻認爲你只有123.29999999999999元,錢不夠,計算機拒絕交易。

(2)、四捨五入

是否能夠四捨五入呢?固然能夠,習慣上咱們本能就會這樣考慮,但四捨五入意味着偏差,商業運算中可能意味着錯誤,同時Java中也沒有提供保留指定位數的四捨五入方法,只提供了一個Math.round(double d)和Math.round(float f)的方法,分別返回長整型和整型值。round方法不能設置保留幾位小數,咱們只能象這樣(保留兩位):

public double round(double value){
  return Math.round( value * 100 ) / 100.0;
}

但很是不幸的是,上面的代碼並不能正常工做,給這個方法傳入4.015它將返回4.01而不是4.02,如咱們在上面看到的

4.015 * 100 = 401.49999999999994

所以若是咱們要作到精確的四捨五入,這種方法不能知足咱們的要求。

還有一種方式是使用java.text.DecimalFormat,但也存在問題,format採用的舍入模式是ROUND_HALF_DOWN(舍入模式在下面有介紹),好比說4.025保留兩位小數會是4.02,由於.025距離」 nearest neighbor」(.02和.03)長度是相等,向下舍入就是.02,若是是4.0251那麼保留兩位小數就是4.03。

System.out.println(new java.text.DecimalFormat("0.00").format(4.025));

System.out.println(new java.text.DecimalFormat("0.00").format(4.0251));

輸出是

4.02

4.03

 

(3)、浮點數輸出(科學記數法)

Java浮點型數值在大於9999999.0就自動轉化爲科學記數法來表示,咱們看下面的例子:

    System.out.println(999999999.04);

    System.out.println(99999999.04);

    System.out.println(10000000.01);

    System.out.println(9999999.04);

輸出的結果以下:

    9.9999999904E8

9.999999904E7

1.000000001E7

9999999.04

    但有時咱們可能不須要科學記數法的表示方法,須要轉換爲字符串,還不能直接用toString()等方法轉換,很煩瑣。

BigDecimal介紹
BigDecimal是Java提供的一個不變的、任意精度的有符號十進制數對象。它提供了四個構造器,有兩個是用BigInteger構造,在這裏咱們不關心,咱們重點看用double和String構造的兩個構造器(有關BigInteger詳細介紹請查閱j2se API文檔)。

BigDecimal(double val)

          Translates a double into a BigDecimal.
 
BigDecimal(String val)

          Translates the String representation of a BigDecimal into a BigDecimal.
 


BigDecimal(double)是把一個double類型十進制數構造爲一個BigDecimal對象實例。

BigDecimal(String)是把一個以String表示的BigDecimal對象構造爲BigDecimal對象實例。

習慣上,對於浮點數咱們都會定義爲double或float,但BigDecimal API文檔中對於BigDecimal(double)有這麼一段話:

Note: the results of this constructor can be somewhat unpredictable. One might assume that new BigDecimal(.1) is exactly equal to .1, but it is actually equal to .10000000000000000555111512312578 27021181583404541015625. This is so because .1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the long value that is being passed in to the constructor is not exactly equal to .1, appearances notwithstanding.

The (String) constructor, on the other hand, is perfectly predictable: new BigDecimal(".1") is exactly equal to .1, as one would expect. Therefore, it is generally recommended that the (String) constructor be used in preference to this one

下面對這段話作簡單解釋:

注意:這個構造器的結果可能會有不可預知的結果。有人可能設想new BigDecimal(.1)等於.1是正確的,但它其實是等於.1000000000000000055511151231257827021181583404541015625,這就是爲何.1不能用一個double精確表示的緣由,所以,這個被放進構造器中的長值並不精確的等於.1,儘管外觀看起來是相等的。

然而(String)構造器,則徹底可預知的,new BigDecimal(「.1」)如同指望的那樣精確的等於.1,所以,(String)構造器是被優先推薦使用的。

看下面的結果:

      System.out.println(new BigDecimal(123456789.02).toString());

      System.out.println(new BigDecimal("123456789.02").toString());

輸出爲:

123456789.01999999582767486572265625

123456789.02

如今咱們知道,若是須要精確計算,非要用String來夠造BigDecimal不可!

實現方案
如今咱們已經知道怎麼解決這個問題了,原則上是使用BigDecimal(String)構造器,咱們建議,在商業應用開發中,涉及金額等浮點數計算的數據,所有定義爲String,數據庫中可定義爲字符型字段,在須要使用這些數據進行運算的時候,使用BigDecimal(String)構造BigDecimal對象進行運算,保證數據的精確計算。同時避免了科學記數法的出現。若是科學記數表示法在應用中不是一種負擔的話,能夠考慮定義爲浮點類型。

 

這裏咱們提供了一個工具類,定義浮點數的加、減、乘、除和四捨五入等運算方法。以供參考。

源文件MathExtend.java:

import java.math.BigDecimal;

public class MathExtend

{

  //默認除法運算精度

  private static final int DEFAULT_DIV_SCALE = 10;

 

 

  public static double add(double v1, double v2)

  {

      BigDecimal b1 = new BigDecimal(Double.toString(v1));

      BigDecimal b2 = new BigDecimal(Double.toString(v2));

      return b1.add(b2).doubleValue();

  }

 

  public static String add(String v1, String v2)

  {

      BigDecimal b1 = new BigDecimal(v1);

      BigDecimal b2 = new BigDecimal(v2);

      return b1.add(b2).toString();

  }

 

 

  public static double subtract(double v1, double v2)

  {

      BigDecimal b1 = new BigDecimal(Double.toString(v1));

      BigDecimal b2 = new BigDecimal(Double.toString(v2));

      return b1.subtract(b2).doubleValue();

  }

 

 

  public static String subtract(String v1, String v2)

  {

      BigDecimal b1 = new BigDecimal(v1);

      BigDecimal b2 = new BigDecimal(v2);

      return b1.subtract(b2).toString();

  }

 

 

 

  public static double multiply(double v1, double v2)

  {

      BigDecimal b1 = new BigDecimal(Double.toString(v1));

      BigDecimal b2 = new BigDecimal(Double.toString(v2));

      return b1.multiply(b2).doubleValue();

  }

 

 

  public static String multiply(String v1, String v2)

  {

      BigDecimal b1 = new BigDecimal(v1);

      BigDecimal b2 = new BigDecimal(v2);

      return b1.multiply(b2).toString();

  }

 

 

  public static double divide(double v1, double v2)

  {

      return divide(v1, v2, DEFAULT_DIV_SCALE);

  }

 

 

  public static double divide(double v1,double v2, int scale)

  {

      return divide(v1, v2, scale, BigDecimal.ROUND_HALF_EVEN);

  }

 

 

  public static double divide(double v1,double v2,int scale, int round_mode){

          if(scale < 0)

          {

              throw new IllegalArgumentException("The scale must be a positive integer or zero");

          }

          BigDecimal b1 = new BigDecimal(Double.toString(v1));

          BigDecimal b2 = new BigDecimal(Double.toString(v2));

          return b1.divide(b2, scale, round_mode).doubleValue();

  }

 

 

  public static String divide(String v1, String v2)

  {

      return divide(v1, v2, DEFAULT_DIV_SCALE);

  }

 

 

  public static String divide(String v1, String v2, int scale)

  {

      return divide(v1, v2, DEFAULT_DIV_SCALE, BigDecimal.ROUND_HALF_EVEN);

  }

 

 

  public static String divide(String v1, String v2, int scale, int round_mode)

  {

      if(scale < 0)

      {

          throw new IllegalArgumentException("The scale must be a positive integer or zero");

      }

      BigDecimal b1 = new BigDecimal(v1);

      BigDecimal b2 = new BigDecimal(v2);

      return b1.divide(b2, scale, round_mode).toString();

  }

 

 

  public static double round(double v,int scale)

  {

      return round(v, scale, BigDecimal.ROUND_HALF_EVEN);

  }

 

  public static double round(double v, int scale, int round_mode)

  {

     if(scale<0)

     {

         throw new IllegalArgumentException("The scale must be a positive integer or zero");

     }

     BigDecimal b = new BigDecimal(Double.toString(v));

     return b.setScale(scale, round_mode).doubleValue();

  }

 

 

  public static String round(String v, int scale)

  {

    return round(v, scale, BigDecimal.ROUND_HALF_EVEN);

  }

 

  public static String round(String v, int scale, int round_mode)

  {

     if(scale<0)

     {

         throw new IllegalArgumentException("The scale must be a positive integer or zero");

     }

     BigDecimal b = new BigDecimal(v);

     return b.setScale(scale, round_mode).toString();
  }
}

BigDecimal 舍入模式(Rounding mode)介紹:
BigDecimal定義了一下舍入模式,只有在做除法運算或四捨五入時纔用到舍入模式,下面簡單介紹,詳細請查閱J2se API文檔

static int
 ROUND_CEILING

          Rounding mode to round towards positive infinity.

向正無窮方向舍入
 
static int
 ROUND_DOWN

          Rounding mode to round towards zero.

向零方向舍入
 
static int
 ROUND_FLOOR

          Rounding mode to round towards negative infinity.

向負無窮方向舍入
 
static int
 ROUND_HALF_DOWN

          Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.

向(距離)最近的一邊舍入,除非兩邊(的距離)是相等,若是是這樣,向下舍入, 例如1.55 保留一位小數結果爲1.5
 
static int
 ROUND_HALF_EVEN

          Rounding mode to round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor.

向(距離)最近的一邊舍入,除非兩邊(的距離)是相等,若是是這樣,若是保留位數是奇數,使用ROUND_HALF_UP ,若是是偶數,使用ROUND_HALF_DOWN
 
static int
 ROUND_HALF_UP

          Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.

向(距離)最近的一邊舍入,除非兩邊(的距離)是相等,若是是這樣,向上舍入, 1.55保留一位小數結果爲1.6
 
static int
 ROUND_UNNECESSARY

          Rounding mode to assert that the requested operation has an exact result, hence no rounding is necessary.

計算結果是精確的,不須要舍入模式
 
static int
 ROUND_UP

          Rounding mode to round away from zero.

向遠離0的方向舍入

相關文章
相關標籤/搜索