浮點數精確計算

來看一道題(http://poj.org/problem?id=1001),如下:


Exponentiation

Time Limit: 500MS   Memory Limit: 10000K
Total Submissions: 111481   Accepted: 27078

Description

Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems. 

This problem requires that you write a program to compute the exact value of Rn where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.

Input

The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.

Output

The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer.

Sample Input

95.123 12
0.4321 20
5.1234 15
6.7592  9
98.999 10
1.0100 12

Sample Output

548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201


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


開始採用Java的double數據類型,始終計算不精確。

查閱資料後,想到Java中的BigDecimal數據類型。

來看看JDK中關於BigDecimal的描述——

public class BigDecimal
extends Numberimplements Comparable<BigDecimal>

不可變的、任意精度的有符號十進制數。BigDecimal 由任意精度的整數非標度值 和 32 位的整數標度 (scale) 組成。如果爲零或正數,則標度是小數點後的位數。如果爲負數,則將該數的非標度值乘以 10 的負 scale 次冪。因此,BigDecimal 表示的數值是(unscaledValue × 10-scale)。  

BigDecimal 類提供以下操作:算術、標度操作、舍入、比較、哈希算法和格式轉換。toString() 方法提供BigDecimal 的規範表示形式。 

public BigDecimal(double val)
double 轉換爲 BigDecimal,後者是 double 的二進制浮點值準確的十進制表示形式。返回的BigDecimal 的標度是使 (10scale × val) 爲整數的最小值。

注:

  1. 此構造方法的結果有一定的不可預知性。有人可能認爲在 Java 中寫入new BigDecimal(0.1) 所創建的 BigDecimal 正好等於 0.1(非標度值 1,其標度爲 1),但是它實際上等於 0.1000000000000000055511151231257827021181583404541015625。這是因爲 0.1 無法準確地表示爲double(或者說對於該情況,不能表示爲任何有限長度的二進制小數)。這樣,傳入 到構造方法的值不會正好等於 0.1(雖然表面上等於該值)。
  2. 另一方面,String 構造方法是完全可預知的:寫入new BigDecimal("0.1") 將創建一個 BigDecimal,它正好 等於預期的 0.1。因此,比較而言,通常建議優先使用String 構造方法
  3. double 必須用作 BigDecimal 的源時,請注意,此構造方法提供了一個準確轉換;它不提供與以下操作相同的結果:先使用Double.toString(double) 方法,然後使用 BigDecimal(String) 構造方法,將double 轉換爲 String。要獲取該結果,請使用 static valueOf(double) 方法。

參數:
val - 要轉換爲 BigDecimaldouble 值。
拋出:
NumberFormatException - 如果 val 爲無窮大或 NaN。


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

因此可以,採用BigDecimal進行計算,構造方法傳入參數爲String類型即可。

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

public class Main {

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		while (true) {
			try {
				double a = scan.nextDouble();
				int b = scan.nextInt();

				System.out.println(trim0(myPower(a, b).toPlainString()));
			} catch (Exception e) {
				return;
			}
		}
	}

	public static BigDecimal myPower(double num, int n) {
		BigDecimal a = new BigDecimal(String.valueOf(num));
		BigDecimal res = new BigDecimal("1.0");
		for (int i = 0; i < n; i++) {
			res = res.multiply(a);
		}
		return res;
	}

	public static String trim0(String data) {
		int startPos = 0, endPos = data.length() - 1;
		while (data.charAt(startPos) == '0')
			startPos++;
		while (data.charAt(endPos) == '0')
			endPos--;
		if (data.indexOf('.') == endPos)
			endPos--;
		return data.substring(startPos, endPos + 1);
	}
} 


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