除大数
Dividing BigDecimals
正在尝试处理 BigDecimals。
尝试除以 BigDecimals 时收到算术异常,比如 10 除以 3(结果是周期值)。
如果我使用指定位数的舍入:如果是 10 / 3,我将得到正确的结果 3.3333333,
但如果是 10 / 8,我会收到 1.25000000。我想在第一种情况下收到 3.33333333 和 1.25.
是否有通用的解决方案?
我的代码是:
BigDecimal b1 = new BigDecimal("10");
BigDecimal b2 = new BigDecimal("3");
try {
// updated
BigDecimal b3 = b1.divide(b2, 8, RoundingMode.HALF_UP);
System.out.println(b3.toString());
} catch (ArithmeticException e) {
System.out.println("Oops");
}
例如,您需要一个 RoundingMode:
BigDecimal b3 = b1.divide(b2, 2, RoundingMode.HALF_UP);
此处全部解释:Stack Overflow - ArithmeticException: “Non-terminating decimal expansion; no exact representable decimal result”。
使用你的解决方案 b3 = b1.divide(b2, 8, RoundingMode.HALF_UP); (8 位数)。它在 10 / 3 的情况下工作正常,但在 10 / 8 的情况下我收到结果 1.25000000。我想在第一种情况下收到 3.88888888,在第二种情况下收到 1.25。如何做到这一点?
你需要一个额外的静态辅助方法,我的完整解决方案:
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalDivider {
public static BigDecimal divideAutoScale(BigDecimal val1, BigDecimal val2,
int scale, RoundingMode roundingMode) {
BigDecimal result = val1.divide(val2, scale, roundingMode);
return result.setScale(countScale(result));
}
/*
* Static helper method, returns int scale.
*/
private static int countScale(BigDecimal bd) {
if (bd.doubleValue() % 2 == 0) {
return 0;
} else {
String bigDec = bd.toString();
int counter = 0;
for (int i = bigDec.length() - 1; i >= 0; i--) {
if (bigDec.charAt(bigDec.length() - 1) != '0') {
break;
}
if (bigDec.charAt(i) == '0') {
counter++;
}
if (bigDec.charAt(i) == '.'
|| (i > 1 && bigDec.charAt(i) == '0' && bigDec
.charAt(i - 1) != '0')) {
break;
}
}
return bigDec.substring(bigDec.indexOf('.'), bigDec.length() - 1)
.length() - counter;
}
}
/*
* Example of usage
*/
public static void main(String[] args) {
BigDecimal b1 = new BigDecimal("10");
BigDecimal b2 = new BigDecimal("5");
BigDecimal result = divideAutoScale(b1, b2, 4, RoundingMode.HALF_UP);
System.out.println(result);
}
}
结果:5
其他测试:
10 / 3 : 3.3333
10 / 8 : 1.25
正在尝试处理 BigDecimals。 尝试除以 BigDecimals 时收到算术异常,比如 10 除以 3(结果是周期值)。
如果我使用指定位数的舍入:如果是 10 / 3,我将得到正确的结果 3.3333333, 但如果是 10 / 8,我会收到 1.25000000。我想在第一种情况下收到 3.33333333 和 1.25.
是否有通用的解决方案?
我的代码是:
BigDecimal b1 = new BigDecimal("10");
BigDecimal b2 = new BigDecimal("3");
try {
// updated
BigDecimal b3 = b1.divide(b2, 8, RoundingMode.HALF_UP);
System.out.println(b3.toString());
} catch (ArithmeticException e) {
System.out.println("Oops");
}
例如,您需要一个 RoundingMode:
BigDecimal b3 = b1.divide(b2, 2, RoundingMode.HALF_UP);
此处全部解释:Stack Overflow - ArithmeticException: “Non-terminating decimal expansion; no exact representable decimal result”。
使用你的解决方案 b3 = b1.divide(b2, 8, RoundingMode.HALF_UP); (8 位数)。它在 10 / 3 的情况下工作正常,但在 10 / 8 的情况下我收到结果 1.25000000。我想在第一种情况下收到 3.88888888,在第二种情况下收到 1.25。如何做到这一点?
你需要一个额外的静态辅助方法,我的完整解决方案:
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalDivider {
public static BigDecimal divideAutoScale(BigDecimal val1, BigDecimal val2,
int scale, RoundingMode roundingMode) {
BigDecimal result = val1.divide(val2, scale, roundingMode);
return result.setScale(countScale(result));
}
/*
* Static helper method, returns int scale.
*/
private static int countScale(BigDecimal bd) {
if (bd.doubleValue() % 2 == 0) {
return 0;
} else {
String bigDec = bd.toString();
int counter = 0;
for (int i = bigDec.length() - 1; i >= 0; i--) {
if (bigDec.charAt(bigDec.length() - 1) != '0') {
break;
}
if (bigDec.charAt(i) == '0') {
counter++;
}
if (bigDec.charAt(i) == '.'
|| (i > 1 && bigDec.charAt(i) == '0' && bigDec
.charAt(i - 1) != '0')) {
break;
}
}
return bigDec.substring(bigDec.indexOf('.'), bigDec.length() - 1)
.length() - counter;
}
}
/*
* Example of usage
*/
public static void main(String[] args) {
BigDecimal b1 = new BigDecimal("10");
BigDecimal b2 = new BigDecimal("5");
BigDecimal result = divideAutoScale(b1, b2, 4, RoundingMode.HALF_UP);
System.out.println(result);
}
}
结果:5
其他测试:
10 / 3 : 3.3333
10 / 8 : 1.25