题解 P1517 【高精求小数幂】
purinliang · · 题解
这里没有Java的题解,补充一下挺好的。
因为Java在acm-icpc中可以使用,而且天然支持BigDecimal进行高精度小数运算,所以学习一下BigDecimal还是有必要的。
第一次做的时候错了很多次,因为输出格式的原因,BigDecimal默认的toSting()方法在某些情况会变成科学计数法,但是这里要求是平凡的计数法,所以要用BigDecimal的toPlainString()方法转化成准确的字符串。
要用toPlainString()! 要用toPlainString()! 要用toPlainString()!
后面的操作都比较常规,大家都可以看看注释明白。
题外话:BigDecimal的除法和BigInteger略有不同,因为BigDecimal的除法理论上是无限精度的,要是除不尽就必须要截断末尾保留精度。但是这里只用朴素的乘法就没有这个问题。
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext()) {
BigDecimal x=sc.nextBigDecimal();
int n=sc.nextInt();
BigDecimal ans=BigDecimal.ONE;
for(int i=0;i<n;i++) {
ans=ans.multiply(x);
//BigDecimal的乘法需要调用multiply()方法,乘以一个BigDecimal对象,返回一个BigDecimal对象
}
String s=ans.toPlainString();
//在这里要使用toPlainString()方法,默认的toString()方法在某些情况是科学计数法,错了很多次才知道
/*
* 例如样例:
* 0.000001 5
*/
int len=s.length();
int leadzero=-1;
boolean metdot=false;
for(int i=0;i<len;i++) {
if(leadzero==-1&&s.charAt(i)!='0') {
leadzero=i;
//把整数部分的0去掉
}
if(s.charAt(i)=='.') {
metdot=true;
//遇到了小数点,说明是小数
break;
}
}
if(metdot==true) {
s=s.substring(leadzero);
//遇到了小数点,说明是小数
len=s.length();
//重新计算s的长度,因为前面可能截断了整数部分的0
int releadzero=-1;
for(int i=len-1;i>=0;i--) {
if(s.charAt(i)!='0') {
releadzero=i+1;
//遇到第一个非零位置,其后的无效0截断
if(s.charAt(i)=='.') {
releadzero=i;
//遇到第一个非零位置是小数点,连小数点也截断
}
break;
}
}
s=s.substring(0,releadzero);
}
else {
//没有遇到小数点,是整数,不可能有无效0
;
}
System.out.println(s);
}
sc.close();
}
}