106.03.31 Java作業四 各種四捨五入

這次過了死線了才PO啊....
原因可能是最近看的一部電影讓我頗憂鬱
《明天,我要和昨天的妳約會》
不說了,進正題吧QuQ

這次作業是讓我們用Babylonian method來求正數平方根並四捨五入到小數點後第二位


演算法不難照公式打就好
我覺得難的是四捨五入 (突然想到高中zero judge的d561:被秒殺的四捨五入
所以本篇主要記錄我查到的各種四捨五入方法



以下程式我改寫成能夠自訂位數
public static double round(double value, int places){}
//value為想四捨五入的數、places為取到小數點下第幾位

一、Math.round
package rounding;
public class RoundByMathRound {
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
long factor = (long) Math.pow(10, places);
value = value * factor;
long tmp = Math.round(value);
return (double) tmp / factor;
}
}

二、DecimalFormat
package rounding;
import java.text.DecimalFormat;
public class RoundByDecimalFormat {
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
String format = "#.";
for(int i = 0; i < places; i++){
format+="#";
}
DecimalFormat df = new DecimalFormat(format);
return Double.parseDouble(df.format(value));
}
}

三、BigDecimal
package rounding;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class RoundbyBigDecimal {
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
}

四、自幹一個字串處理 (會有bugs,踩雷記錄QuQ)
package rounding;
public class RoundByStringHandling {
public static double round(double value, int places){
if (places < 0) throw new IllegalArgumentException();
StringBuilder sb = new StringBuilder(((Double)(value)).toString());
StringBuilder resultString = null;
double resultValue = 0D;
boolean isFindDot = false;
String avoidOverIndexZero = "";
for(int i = 0; i < places; i++){
avoidOverIndexZero += "0";
}
for(int i = 0; i < sb.length(); i++){
if(sb.charAt(i) == '.'){
isFindDot = true;
sb = sb.append(avoidOverIndexZero);//if value only 1 or 2 decimal add "00" can avoid StringIndexOutOfBoundsException
resultString = new StringBuilder(sb.substring(0, i + places + 2));//.toString();//Cut after 3 decimal String
break;
}
}
if(isFindDot == false){//no dot represent value is integer
return value;
}
else{
int nextDecimal = Integer.parseInt(resultString.substring(resultString.length()-1));
//System.out.println(nextDecimal);
if(nextDecimal >= 5){
resultString.deleteCharAt(resultString.length()-1);
resultValue = Double.parseDouble(resultString.toString())+Math.pow(0.1, places);
}
else{
resultString.deleteCharAt(resultString.length()-1);
resultValue = Double.parseDouble(resultString.toString());
}
}
return resultValue;
}
}


實際測試:(精確度都以2位為測試)
package rounding;
import java.util.Scanner;
public class RoundingTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double num = Double.parseDouble(scanner.nextLine());
System.out.println("Origin:\t"+(num));
double d1 = RoundByMathRound.round(num, 2);
System.out.println("d1:\t" + d1);
double d2 = RoundByDecimalFormat.round(num, 2);
System.out.println("d2:\t" + d2);
double d3 = RoundbyBigDecimal.round(num, 2);
System.out.println("d3:\t" + d3);
double d4 = RoundByStringHandling.round(num, 2);
System.out.println("d4:\t" + d4);
scanner.close();
}
}

結果:

驚人發現在2.345時用字串處理會錯誤,原因應該是某東方神秘力量吧QuQ


參考資料:
Round a double to 2 decimal places [duplicate]

^ Top