編碼中一般遇到金額以及小數點精度計算,爲避免精度丟失,將double類型轉換爲BigDecimal再進行相關計算,或者使用DecimalFormat進行轉換。java
1.BigDecimal
BigDecimal是Java提供的一個不變的、任意精度的有符號十進制數對象,繼承自Number類。BigDecimal類提供了算術操做,操做規模,四捨五入,比較,哈希和格式轉換。git
BigDecimal經常使用的構造方法及普通方法:
- 將double表示形式轉換爲BigDecimal
public BigDecimal(double val)
- 將int表示形式轉換爲BigDecimal
public BigDecimal(int val)
- 將字符串表示形式轉換爲BigDecimal
public BigDecimal(String val)
- 加法
public BigDecimal add(BigDecimal augend)
- 減法
public BigDecimal subtract(BigDecimal subtrahend)
- 乘法
public BigDecimal multiply(BigDecimal multiplicand)
- 除法
public BigDecimal divide(BigDecimal divisor)
- 取餘
public BigDecimal remainder(BigDecimal divisor)
- 求商和餘數
public BigDecimal[] divideAndRemainder(BigDecimal divisor)
- BigDecimal中setScale(int newScale)方法設置保留幾位小數以及舍入模式
public BigDecimal setScale(int newScale) {
return setScale(newScale, RoundingMode.UNNECESSARY);
}
// ......
public BigDecimal setScale(int newScale, int roundingMode) {
return setScale(newScale, RoundingMode.valueOf(roundingMode));
}
BigDecimal常見的計算方法以下:
/** * 加法運算。 * * @param amount1 被加數 * @param amount2 加數 * @return 兩個參數的和 */
public static double add(double amount1, double amount2) {
BigDecimal mDecimal1 = new BigDecimal(Double.toString(amount1));
BigDecimal mDecimal2 = new BigDecimal(Double.toString(amount2));
return mDecimal1.add(mDecimal2).doubleValue();
}
/** * 減法運算。 * * @param amount1 被減數 * @param amount2 減數 * @return 兩個參數的差 */
public static double subtraction(double amount1, double amount2) {
BigDecimal mDecimal1 = new BigDecimal(Double.toString(amount1));
BigDecimal mDecimal2 = new BigDecimal(Double.toString(amount2));
return mDecimal1.subtract(mDecimal2).doubleValue();
}
/** * 乘法運算。 * * @param amount1 被乘數 * @param amount2 乘數 * @return 兩個參數的積 */
public static double multiplication(double amount1, double amount2) {
BigDecimal mDecimal1 = new BigDecimal(Double.toString(amount1));
BigDecimal mDecimal2 = new BigDecimal(Double.toString(amount2));
return mDecimal1.multiply(mDecimal2).doubleValue();
}
/** * 除法運算。 * MathContext.DECIMAL128其精度設置與Decimal128格式,34位數字和 [HALF_EVEN]的舍入模式同樣。 * divide()方法默認爲MathContext.UNLIMITED無限取值,不作限制陷入死循環會拋出ArithmeticException(計算溢出)異常。 * * @param amount1 被除數 * @param amount2 除數 * @return 兩個參數的商 */
public static double divisionOperation(double amount1, double amount2) {
BigDecimal mDecimal1 = new BigDecimal(Double.toString(amount1));
BigDecimal mDecimal2 = new BigDecimal(Double.toString(amount2));
return mDecimal1.divide(mDecimal2, MathContext.DECIMAL128).doubleValue();
}
2.DecimalFormat
DecimalFormat是一個NumberFormat的子類的格式小數。它有各類各樣的功能設計使它能夠解析和格式化數字在任何地區,包括支持西方,阿拉伯語和印度語的數字。它還支持不一樣類型的數據,包括整數(123),定點數(123.4),科學記數法(1.23 e4)百分比(12%)和貨幣數量(123美圓)等。web
DecimalFormat經常使用的構造方法及普通方法:
- 建立一個DecimalFormat使用默認模式(Locale.Category.FORMAT)
public DecimalFormat() {
Locale def = Locale.getDefault(Locale.Category.FORMAT);
// try to get the pattern from the cache
String pattern = cachedLocaleData.get(def);
if (pattern == null) { /* cache miss */
// Get the pattern for the default locale.
pattern = LocaleData.get(def).numberPattern;
/* update cache */
cachedLocaleData.putIfAbsent(def, pattern);
}
this.symbols = new DecimalFormatSymbols(def);
init(pattern);
}
- 建立一個使用給定的DecimalFormat模式和默認
public DecimalFormat(String pattern)
- 建立一個使用給定的DecimalFormat模式和符號。
public DecimalFormat(String pattern, DecimalFormatSymbols symbols)
- 適用於給定的地區設置固定的格式 ,如」#0.00」—>1.25
public void applyPattern(String pattern)
- 格式化生成一個字符串
public final String format(double number)
- 設置格式時這個數字格式所使用的貨幣幣值。
public void setCurrency(Currency currency)
- 設置數的小數部分所容許的最大位數
public void setMaximumFractionDigits(int newValue)
- 設置數的小數部分所容許的最小位數
public void setMinimumFractionDigits(int newValue)
- 設置區域
public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols)
- 設置返回前綴
public void setNegativePrefix(String newValue)
- 設置先後綴
public void setPositiveSuffix(String newValue)
- 設置分組
public void setGroupingUsed(boolean newValue)
- 設置分組大小
public void setGroupingSize(int newValue)
DecimalFormat經常使用方法以下:
/** * 格式化保留兩位小數,默認四捨五入 * * @param amount * @return */
public static String formatTwoDecimals(double amount) {
DecimalFormat mFormat = new DecimalFormat();
// 設置區域
mFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.CHINA));
// 設置格式化保留兩位小數
mFormat.applyPattern("#0.00");
return mFormat.format(amount);
}
/** * 格式化保留兩位小數,只舍不入 * * @param amount * @return */
public static String formatTwoDecimalsDown(double amount) {
DecimalFormat mFormat = new DecimalFormat();
// 設置區域
mFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.CHINA));
// 設置格式化保留兩位小數
mFormat.applyPattern("#0.00");
// 設置只舍不入
mFormat.setRoundingMode(RoundingMode.DOWN);
return mFormat.format(amount);
}
/** * 保留有效數,最多保留兩位 * * @return */
public static String formatTwoEffectiveNumber(double amount) {
DecimalFormat mFormat = new DecimalFormat();
// 設置區域
mFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.CHINA));
// 設置保留兩位有效數
mFormat.applyPattern("#0.##");
// 設置只舍不入
mFormat.setRoundingMode(RoundingMode.DOWN);
return mFormat.format(amount);
}
/** * 金額3位數分組,如10000——>10,000 * * @param amount * @return */
public static String formatAmountGrouping(double amount) {
DecimalFormat mFormat = new DecimalFormat();
// 設置區域
mFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.CHINA));
// 設置使用逗號「,」將金額分隔開
mFormat.setGroupingUsed(true);
// 設置分隔位數
mFormat.setGroupingSize(3);
return mFormat.format(amount);
}
DecimalFormat中格式字符說明
符號 | 位置 | 本地化 | 含義 |
---|---|---|---|
0 | 數字 | 是 | 阿拉伯數字 |
# | 數字 | 是 | 阿拉伯數字,若是不存在則顯示爲空 |
. | 數字 | 是 | 小數分隔符或貨幣小數分隔符 |
- | 數字 | 是 | 缺省負數前綴 |
, | 數字 | 是 | 分組分隔符 |
E | 數字 | 是 | 分隔科學計數法中的尾數和指數。在前綴或後綴中無需加引號 |
% | 前綴或後綴 | 是 | 乘以100和做爲百分比顯示 |
/u2030 | 前綴或後綴 | 是 | 乘以1000並顯示爲千分數 |
3.BigDecimal和DecimalFormat中保留小數位進行舍入模式都是RoundingMode模式
源碼以下:app
public enum RoundingMode {
/** * 向上進位,如: * 2.56計算後保留一位小數則爲2.6 * 1.1保留整數則爲2 * -2.5保留整數爲-3 */
UP(BigDecimal.ROUND_UP),
/** * 舍入模式爲零。 */
DOWN(BigDecimal.ROUND_DOWN),
/** * 舍入模式正無窮。 */
CEILING(BigDecimal.ROUND_CEILING),
/** * 舍入模式向負無窮。 */
FLOOR(BigDecimal.ROUND_FLOOR),
/** * 舍入模式向「最近鄰」輪除非鄰居都是等距的,在這種狀況下一輪。 */
HALF_UP(BigDecimal.ROUND_HALF_UP),
/** * 舍入模式向「最近鄰」輪除非鄰居都是等距的,在這種狀況下一輪下來。 */
HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
/** * 舍入模式向「最近鄰」輪除非鄰居都是等距的,在這種狀況下,甚至向鄰居。 */
HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
/** * 舍入模式斷言請求的操做有一個確切的結果,所以不須要舍入。 */
UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
private final int bigDecimalRM;
RoundingMode(int rm) {
bigDecimalRM = rm;
}
/** * 返回與指定名稱這種類型的枚舉常量。 * 字符串必須匹配徹底一個標識符用於聲明一個枚舉常數在這個類型。 (多餘的空格字符是不容許的。) 參數 */
public static RoundingMode valueOf(int mode) {
switch (mode) {
case BigDecimal.ROUND_CEILING:
return CEILING;
case BigDecimal.ROUND_DOWN:
return DOWN;
case BigDecimal.ROUND_FLOOR:
return FLOOR;
case BigDecimal.ROUND_HALF_DOWN:
return HALF_DOWN;
case BigDecimal.ROUND_HALF_EVEN:
return HALF_EVEN;
case BigDecimal.ROUND_HALF_UP:
return HALF_UP;
case BigDecimal.ROUND_UNNECESSARY:
return UNNECESSARY;
case BigDecimal.ROUND_UP:
return UP;
default:
throw new IllegalArgumentException("Invalid rounding mode");
}
}
}
本文分享 CSDN - 秦川小將。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。ide