浮点数精确计算

来看一道题(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 R n 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 Number
implements Comparable< BigDecimal>

不可变的、任意精度的有符号十进制数。BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale 次幂。因此,BigDecimal 表示的数值是(unscaledValue × 10-scale)。  

BigDecimal 类提供以下操作:算术、标度操作、舍入、比较、哈希算法和格式转换。 toString() 方法提供 BigDecimal 的规范表示形式。 

public BigDecimal(double val)
将 double 转换为 BigDecimal,后者是 double 的二进制浮点值准确的十进制表示形式。返回的 BigDecimal 的标度是使 (10 scale × 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 - 要转换为 BigDecimal 的 double 值。
抛出:
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);
	}
} 


你可能感兴趣的:(浮点数精确计算)