一、double和float直接進行運算會丟失精度
double d = 0.58;
// 57.99999999999999 精度丟失
System.out.println(d * 100);
double d2 = 65.21;
// 0.6520999999999999 精度丟失
System.out.println(d2 / 100);
float f = 0.05f;
float f1 = 0.01f;
// 0.060000002 丟失精度
System.out.println(f + f1);
二、double和float封裝成BigDecimal進行運算可以保留精度,但必須以String類型爲入參的構造器構造BigDecimal對象才行。
double d = 0.58;
// 57.99999999999999 精度丟失
System.out.println(d * 100);
// 其他double、int、long構造器都會進行舍入,丟失精度
BigDecimal decimal = new BigDecimal(d);
// 必須爲String的構造器纔不會丟失精度
BigDecimal decimal2 = new BigDecimal(String.valueOf(d));
// 57.99999999999999 精度丟失
System.out.println(decimal.multiply(new BigDecimal(100)).doubleValue());
// 58.0 精度沒有丟失
System.out.println(decimal2.multiply(new BigDecimal(100)).doubleValue());
BigDecimal.valueOf內部用的就是String類型參數的構造器,所以用BigDecimal.valueOf可以保留精度
double d2 = 65.21;
// 0.6520999999999999 精度丟失
System.out.println(d2 / 100);
// 0.6521 不會丟失精度,內部會轉換爲String的構造器
System.out.println(BigDecimal.valueOf(d2).divide(BigDecimal.valueOf(100)));
// 丟失精度
System.out.println(new BigDecimal(d2).divide(BigDecimal.valueOf(100)));
三、float強轉double也會丟失精度,float需要先轉成String,再轉成double,就不會丟失精度
float f = 0.05f;
float f1 = 0.01f;
// 0.060000002 丟失精度
System.out.println(f + f1);
// 0.060000000521540642 丟失精度,float直接轉double會涉及精度問題
System.out.println(BigDecimal.valueOf(f).add(BigDecimal.valueOf(f1)));
// 0.06 不丟失精度
System.out.println(new BigDecimal(String.valueOf(f)).add(new BigDecimal(String.valueOf(f1))));
double d = f;
// 0.05000000074505806, float直接轉double會丟失精度
System.out.println(d);
double d2 = Double.parseDouble(String.valueOf(f));
// 0.05 float -> String -> double 不會丟失精度
System.out.println(d2);
四、DecimalFormat對double進行格式化時,也可能會丟失精度。需要設置decimalFormat.setParseBigDecimal(true),以BigDecimal去解析,就不會丟失精度
String pattern = "#.##%";
DecimalFormat decimalFormat = new DecimalFormat(pattern);
Number num = decimalFormat.parse("65.21%");
// Double: 0.6520999999999999 丟失精度
System.out.println(num.getClass().getSimpleName() + ": " + num);
// 設置DecimalFormat以BigDecimal去解析,不會丟失精度
decimalFormat.setParseBigDecimal(true);
Number n = decimalFormat.parse("65.21%");
// BigDecimal: 0.6521 沒有丟失精度
System.out.println(n.getClass().getSimpleName() + ": " + n);
五、DecimalFormat格式化用例
//#:比實際數字的位數多,不變。比實際數字的位數少:整數部分不改動,小數部分,四捨五入
String pattern = "#.##%";
DecimalFormat decimalFormat = new DecimalFormat(pattern);
System.out.println(decimalFormat.parse("2.4%"));//0.024
System.out.println(decimalFormat.format(0.6521));//65.21%
System.out.println(decimalFormat.format(0.652566));//65.26%
System.out.println(new DecimalFormat("##.##").format(3.14));//3.14
System.out.println(new DecimalFormat("##.#").format(3.14));//3.1
System.out.println(new DecimalFormat("##.#").format(323.14));//323.1
//0:比實際數字的位數多,不足的地方用0補上,比實際數字的位數少:整數部分不改動,小數部分,四捨五入
System.out.println(new DecimalFormat("00.00").format(3.14));//03.14
System.out.println(new DecimalFormat("00.000").format(3.14));//03.140
System.out.println(new DecimalFormat("00.0").format(3.14));//03.1
System.out.println(new DecimalFormat("0.0").format(3.14));//3.1
System.out.println(new DecimalFormat("#.00%").format(13.146));//1314.60%
long c = 299792458;
//五位小數科學計數法2.99792E8
System.out.println(new DecimalFormat("#.#####E0").format(c));
//兩位整數四位小數29.9792E7
System.out.println(new DecimalFormat("00.####E0").format(c));
//每三位用逗號隔開
System.out.println(new DecimalFormat(",###").format(c));
//和文本拼接
System.out.println(new DecimalFormat("光速大小爲:###m/s").format(c));