1. 程式人生 > >java除法保留小數問題

java除法保留小數問題

java保留兩位小數問題:

方式一:

四捨五入 
double   f   =   111231.5585; 
BigDecimal   b   =   new   BigDecimal(f); 
double   f1   =   b.setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue(); 
保留兩位小數 
--------------------------------------------------------------- 

方式二:

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

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

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

方式三:

double d = 3.1415926;

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

%.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;

 /**

  * 提供精確的加法運算。

  * @param v1

  * @param v2

  * @return 兩個引數的和

  */

  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();

  }

  /**

   * 提供精確的加法運算

   * @param v1  

   * @param v2

   * @return 兩個引數數學加和,以字串格式返回

   */

  public static String add(String v1, String v2)

  {

      BigDecimal b1 = new BigDecimal(v1);

      BigDecimal b2 = new BigDecimal(v2);

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

  }

 /**

  * 提供精確的減法運算。

  * @param v1

  * @param v2

  * @return 兩個引數的差

  */

  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();

  }

  /**

   * 提供精確的減法運算

   * @param v1

   * @param v2

   * @return 兩個引數數學差,以字串格式返回

   */

  public static String subtract(String v1, String v2)

  {

      BigDecimal b1 = new BigDecimal(v1);

      BigDecimal b2 = new BigDecimal(v2);

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

  }

  /**

  * 提供精確的乘法運算。

  * @param v1

  * @param v2

  * @return 兩個引數的積

  */

  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();

  }

  /**

   * 提供精確的乘法運算

   * @param v1

   * @param v2

   * @return 兩個引數的數學積,以字串格式返回

   */

  public static String multiply(String v1, String v2)

  {

      BigDecimal b1 = new BigDecimal(v1);

      BigDecimal b2 = new BigDecimal(v2);

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

  }

  /**

  * 提供(相對)精確的除法運算,當發生除不盡的情況時,精確到

  * 小數點以後10位,以後的數字四捨五入,舍入模式採用ROUND_HALF_EVEN

  * @param v1

  * @param v2

  * @return 兩個引數的商

  */

  public static double divide(double v1, double v2)

  {

      return divide(v1, v2, DEFAULT_DIV_SCALE);

  }

  /**

   * 提供(相對)精確的除法運算。當發生除不盡的情況時,由scale引數指

   * 定精度,以後的數字四捨五入。舍入模式採用ROUND_HALF_EVEN

   * @param v1

   * @param v2

   * @param scale 表示需要精確到小數點以後幾位。

   * @return 兩個引數的商

   */

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

  {

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

  }

  /**

   * 提供(相對)精確的除法運算。當發生除不盡的情況時,由scale引數指

   * 定精度,以後的數字四捨五入。舍入模式採用使用者指定舍入模式

   * @param v1

   * @param v2

   * @param scale 表示需要精確到小數點以後幾位

   * @param round_mode 表示使用者指定的舍入模式

   * @return 兩個引數的商

   */

  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();

  }

  /**

   * 提供(相對)精確的除法運算,當發生除不盡的情況時,精確到

   * 小數點以後10位,以後的數字四捨五入,舍入模式採用ROUND_HALF_EVEN

   * @param v1

   * @param v2

   * @return 兩個引數的商,以字串格式返回

   */

  public static String divide(String v1, String v2)

  {

      return divide(v1, v2, DEFAULT_DIV_SCALE);

  }

  /**

   * 提供(相對)精確的除法運算。當發生除不盡的情況時,由scale引數指

   * 定精度,以後的數字四捨五入。舍入模式採用ROUND_HALF_EVEN

   * @param v1

   * @param v2

   * @param scale 表示需要精確到小數點以後幾位

   * @return 兩個引數的商,以字串格式返回

   */

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

  {

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

  }

  /**

   * 提供(相對)精確的除法運算。當發生除不盡的情況時,由scale引數指

   * 定精度,以後的數字四捨五入。舍入模式採用使用者指定舍入模式

   * @param v1

   * @param v2

   * @param scale 表示需要精確到小數點以後幾位

   * @param round_mode 表示使用者指定的舍入模式

   * @return 兩個引數的商,以字串格式返回

   */

  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();

  }

  /**

   * 提供精確的小數位四捨五入處理,舍入模式採用ROUND_HALF_EVEN

   * @param v 需要四捨五入的數字

   * @param scale 小數點後保留幾位

   * @return 四捨五入後的結果

   */

  public static double round(double v,int scale)

  {

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

  }

  /**

   * 提供精確的小數位四捨五入處理

   * @param v 需要四捨五入的數字

   * @param scale 小數點後保留幾位

   * @param round_mode 指定的舍入模式

   * @return 四捨五入後的結果

   */

  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();

  }

  /**

   * 提供精確的小數位四捨五入處理,舍入模式採用ROUND_HALF_EVEN

   * @param v 需要四捨五入的數字

   * @param scale 小數點後保留幾位

   * @return 四捨五入後的結果,以字串格式返回

   */

  public static String round(String v, int scale)

  {

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

  }

  /**

   * 提供精確的小數位四捨五入處理

   * @param v 需要四捨五入的數字

   * @param scale 小數點後保留幾位

   * @param round_mode 指定的舍入模式

   * @return 四捨五入後的結果,以字串格式返回

   */

  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的方向舍入
 

相關推薦

java除法保留小數問題

java保留兩位小數問題: 方式一: 四捨五入  double   f   =   111231.5585;  BigDecimal   b   =   new   BigDecimal(f);  double   f1   =   b.setScale(2,   BigDe

Java除法保留小數、百分數

1、int 相除只保留整數位,若保留小數點後2位先乘以100再除以100 2、double 相除精確到小數點後多位,通過DecimalFormat 設定保留小 數點後位數,0.00保留2位 3、百分數,通過NumberFormat獲得百分數例項

Java指定保留小數位數的方法

小數位數 mode down ceil package style spa 直接 obj package com.qiyuan.util; import java.math.BigDecimal; import java.math.RoundingMode; impor

SQL中除法保留小數decimal(a,b)

decimal(a,b) a指定指定小數點左邊和右邊可以儲存的十進位制數字的最大個數,最大精度38。 b指定小數點右邊可以儲存的十進位制數字的最大個數。小數位數必須是從 0 到 a之間的值。預設小數位數是 0。 例子:SELECT CONVERT(DECI

postgreSQL除法保留小數

col post cast postgresq postgres -- row pos 保留小數 --1 例子postgres=# select 1/4; ?column? ---------- 0(1 row) 在PG裏如果想做除法並想保留

java BigDecimal加法/減法/乘法/除法 保留兩位小數

1.BigDecimal類概述及其構造方法   由於在運算的時候,float型別和double型別很容易丟失進度,所以,為了能夠精確的表示、計算浮點數,java提供了BigDecimal類   BigDecimal類是不可變得、任意精度的有符號是進位制數 2.構造方法及成

java 除法結果保留兩位小數小數保留前導零

  DecimalFormat df1 = new DecimalFormat(“0.0″); //保留1位小數,帶前導零 DecimalFormat df2 = new DecimalFormat(“#.#”); //保留1位小數,可以不帶前導零 DecimalForma

Java float保留兩位小數或多位小數

plain ima itl highlight border 十進制 syn 兩位小數 ice 方法1:用Math.round計算,這裏返回的數字格式的. 1 2 3 4 float price=89.89; int itemNum=3; fl

JAVA保留小數問題,基礎)Probability hdu2131

-s his lan ins after rec accep rst new Probability 鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2131 Time Limit: 3000/1000 MS (Java/Oth

Java保留指定小數位數

方式一: import java.math.BigDecimal; /* * 計算並輸出1/3.0的值,保留小數點後2位 * 方式一:四捨五入 */ public class Main{ public static void main(String[] args){ doubl

java 四捨五入保留兩位小數

寫 專案時遇到,從後臺傳來字串格式的引數進行乘法計算。將其結果四捨五入保留兩位小數,寫了個方法 主要用到 java.math.BigDecimal這個類 /**      *       * @param j

java : 保留小數位數的方法

Ex :     double a=1.2356;     //方法1     double b=(double)Math.round(a*100)/100;  //1.23     //方法2     String s1=String.format("%.2f",a);

sql sql計算除法保留兩位小數sql中分母為零處理

1  select   d.name, case when SUM(a.grid_capacity)=0 then 0 else ROUND(SUM(c.year_power)/SUM(a.grid_capacity), 2)   end as 'hours',

Java計算兩個經緯度之間的距離公式,外加百度地圖高德地圖轉換,和保留小數

在網上看到了很多兩個座標之間的距離公式,也都親自測試了,有很多都不可以用,後來找到一個比較好的距離演算法,分享給大家 經緯度兩點之間的距離公式 public class MapUtils { private static double rad(double d) { return

java保留2位小數的四種方法

在寫程式的時候,有時候可能需要設定小數的位數,那麼java中有哪幾種保留小數位數的方法呢?本文以兩位小數為例給出四種方法。 package CodeJava_Leet; import java.math.BigDecimal; import java.text.DecimalFormat;

Python中的除法保留兩位小數

在C/C++語言對於整形數執行除法會進行地板除(捨去小數部分)。例如 int a=15/10; a的結果為1。 同樣的在Java中也是如此,所以兩個int型的資料相除需要返回一個浮點型資料的時候就需要強制型別轉換,例如 float a = (float)b/c

BigDecimal除法函式保留小數和四捨五入

商=被除數.devide(除數,保留小數位數,精確方法) 120/100 ,150/100 ,180/100 值均為2 public static int divide(String v1, String v2){ BigDecimal

c語言除法如何保留小數,如何printf小數 [程式設計題] 字串碎片

#include<stdio.h> #include<string.h> char str[51]; int n,count,i; int main() {     scanf("%s",&str);     n=strlen(str);  

java BigDecimal用法詳解(保留小數,四捨五入,數字格式化,科學計數法轉數字等)

一、簡介    Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數進行精確的運算。雙精度浮點型變數double可以處理16位有效數。在實際應用中,需要對更大或者更小的數進行運算和處理。float和double只能用來做科學計算或者是

Java中四捨五入保留兩位小數或不保留小數

//四捨五入,不保留小數; float gr = 8;float gc = 3;DecimalFormat df1 = new DecimalFormat("0");//格式化小數,不足的補0 Str