對於高精度或者運算數較大的計算,應該使用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) |
BigDecimal(String val) |
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 .100000000000000005551115
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是正確的,但它實際上是等於.100000000000000005551115
然而(String)構造器,則完全可預知的,new BigDecimal(“.1”)如同期望的那樣精確的等於.1,因此,(String)構造器是被優先推薦使用的。
看下面的結果:
輸出爲:
123456789.019999995827674865722656
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)
{
}
public static String add(String v1, String v2)
{
}
public static double subtract(double v1, double v2)
{
}
public static String subtract(String v1, String v2)
{
}
public static double multiply(double v1, double v2)
{
}
public static String multiply(String v1, String v2)
{
}
public static double divide(double v1, double v2)
{
}
public static double divide(double v1,double v2, int scale)
{
}
public static double divide(double v1,double v2,int scale, int round_mode){
}
public static String divide(String v1, String v2)
{
}
public static String divide(String v1, String v2, int scale)
{
}
public static String divide(String v1, String v2, int scale, int round_mode)
{
}
public static double round(double v,int scale)
{
}
public static double round(double v, int scale, int round_mode)
{
}
public static String round(String v, int scale)
{
}
public static String round(String v, int scale, int round_mode)
{
}
}