使用BigDecimal+while循環計算1+1/2!+1/3!+...+1/n

對於高精度或者運算數較大的計算,應該使用BigDecimal類(浮點數)或者BigInteger類(整數)來實現,否則JAVA基本類型的數據無法保證浮點數的精確,如下例。

import java.math.BigDecimal;
import java.util.Scanner;

//計算階乘和
public class WhileCal {

 public static void main(String[] args) {
  Scanner sc=new Scanner(System.in);
  System.out.println("輸入t的值:");
  int t=sc.nextInt();
  BigDecimal sum=new BigDecimal(0.0);
  BigDecimal factorial=new BigDecimal(1.0);
  int i=1;
  while(i<=t){
   sum=sum.add(factorial);//求各階乘之和
   ++i;
   factorial=factorial.multiply(new BigDecimal(1.0/i));//求階乘
  }
  System.out.println("1+1/2!......+1/t!="+sum);
 }

}

以下內容摘自網絡:

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

}

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

}

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

}

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

}

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

}

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

}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章