OpenJudge—1001:Exponentiation
刷題之百練oj。決定往java方向發展的我希望能用java刷這些oj上的題目;莫名其妙使用了java之後不習慣從底層考慮問題了,一直想要調用什麼方法;然而自己對很多方法都還不了解,是以這個位置很尴尬。不多說了,這個題目其實很簡單,但對于無知的我而言還有很多都不懂,需要總結。
遇到的問題有:
1.如何處理大整數問題?讀入大整數,大整數的乘方運算?
2.計算之後如何處理題目中對輸出結果的要求?如不能有前邊的0?不能有多餘的無意義的0?
3.正規表達式的回顧和使用(還不熟練)?
4.如何找出樣例來debug?
解決過程:
1.首先java中有BigDecimal這個類用來表示精度比較大的數;類中的方法包含的對大整數的加減乘除、乘方等,調用方法和int等數不太一樣;通過查手冊即可了解到。
BigDecimal.pow(int n)
2.最開始處理的是結尾的0以及開頭的0的問題,這兩個解決的也很容易,隻需要找到有效位的起點和終點,然後輸出中間部分就可以了。但是出現的問題在于第一步中的結果是用科學記數法表示的,于是需要處理後邊的指數部分和前邊小數點的移位問題。
在這個過程中用到了正規表達式,主要目的是找到小數點移動的位數,進而恢複出原始的資料。下述代碼就找到了最後的指數。
String pattern="(\\d*)(\\.*)(\\d+)(E-)(\\d+)";
Pattern r=Pattern.compile(pattern);
Matcher m=r.matcher(sb);
if(m.find()){
flag=Integer.parseInt(m.group());
}
其實這裡還存在一個問題是,我的這種做法僅限于指數為負。
3.正規表達式的使用,以及正規表達式的定義了。
Pattern、Pattern.compile、Matcher、matcher()、find()
其中Pattern可以了解為定義一個正則規則
Matcher可以了解為字元串對規則進行比對後的結果
此外,在比對的結果中group(0)存放的是整個字元串、剩下的是按括号進行存儲的内容
4.找樣例。本來是想用對拍程式的,有點麻煩,于是自己自動産生大量資料,然後找了一個已經通過的程式,找不同……
收獲
看了其他人的writeup,很多是将大數計算從底層實作了一遍,大緻思路是,将小數點先删掉,并記錄下它的位置以便之後恢複使用。然後剩下的位數進行乘法計算,以字元串的形式進行計算,這部分也是一個難點,涉及到進位等問題;此外将乘方運算簡化為多次乘法運算;最後将小數點放在合适的位置。
java中有兩個方法這裡如果使用的話會很簡便:
stripTrailingZeros():作用是删掉後邊多餘的0
roPlainString():作用是不使用科學記數法輸出
貼代碼
import java.math.*;
import java.util.Scanner;
import java.util.regex.*;
public class Exponentiation {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
String pattern="(\\d*)(\\.*)(\\d+)(E-)(\\d+)";
Pattern r=Pattern.compile(pattern);
while(sc.hasNext()){
BigDecimal bd=sc.nextBigDecimal();
int x=sc.nextInt();
BigDecimal re=bd.pow(x);
String sb=re.toString();
//System.out.println(sb);
int start=,end=sb.length()-,flag=;
Matcher m=r.matcher(sb);
if(m.find()){
flag=Integer.parseInt(m.group());
sb=m.group()+m.group()+m.group();
end=end--m.group().length();
}
//System.out.println(flag);
if(sb.charAt()=='0'){
start=;
//end=;
//flag=;
}
while(end!=){
if(sb.charAt(end)=='0'){
end--;
}
else{
break;
}
}
if(sb.charAt(end)=='.'){
end--;
}
if(flag!=&&sb.charAt(start)!='0'){
System.out.print('.');
for(int k=;k<flag;k++){
System.out.print("0");
}
System.out.print(sb.charAt());
start=;
}
for(int i=start;i<=end;i++){
System.out.print(sb.charAt(i));
}
System.out.println();
}
sc.close();
}
}