如何使用BigDecimal提升整数倒数反正切计算方法的精度
修改后的BigDecimal版本实现
import java.math.BigDecimal; import java.math.RoundingMode; public static BigDecimal atanInvInt(int x) { // 可根据实际精度需求调整保留小数位数 final int SCALE = 50; final RoundingMode ROUND_MODE = RoundingMode.HALF_UP; final BigDecimal ONE = BigDecimal.ONE; final BigDecimal ZERO = BigDecimal.ZERO; // Returns the arc tangent of an inverse integer /* Terminates once the remaining amount reaches zero or the denominator reaches 2101. If the former happens, the accuracy should be determined by the number format used, such as double. If the latter happens, the result should be off by at most one from the correct nearest value in the seventh decimal place, if allowed by the accuracy of the number format used. This likely only happens if the integer is 1. */ BigDecimal xBD = BigDecimal.valueOf(x); // 转long避免x过大时x*x出现int溢出 BigDecimal xSquareBD = BigDecimal.valueOf((long) x * x); BigDecimal result = ONE.divide(xBD, SCALE, ROUND_MODE); BigDecimal term = ONE.divide(xBD, SCALE, ROUND_MODE); int divisor = 1; BigDecimal midResult; while (term.compareTo(ZERO) > 0) { term = term.divide(xSquareBD, SCALE, ROUND_MODE); divisor += 2; midResult = result.subtract(term.divide(BigDecimal.valueOf(divisor), SCALE, ROUND_MODE)); term = term.divide(xSquareBD, SCALE, ROUND_MODE); divisor += 2; result = midResult.add(term.divide(BigDecimal.valueOf(divisor), SCALE, ROUND_MODE)); if (divisor >= 2101) { return result.add(midResult).divide(BigDecimal.valueOf(2), SCALE, ROUND_MODE); } } return result; }
关键修改说明
- 所有浮点变量全部替换为
BigDecimal类型,运算统一使用BigDecimal提供的add/subtract/multiply/divide方法,不能直接使用算术运算符 - 除法运算必须显式指定保留精度和舍入模式,避免出现无限小数时抛出
ArithmeticException,代码中设置的保留50位小数可根据你的实际精度需求调整 - 数值比较使用
compareTo方法,不能直接使用大于/小于/等于符号 - 如果要改用
BigInteger存储xSquare的累乘值避免多次除法的累计精度损失,可新增BigInteger xSquarePow = BigInteger.valueOf(x)变量,每次循环累乘x平方的BigInteger值,再转为BigDecimal参与运算即可,适合超高精度计算场景
内容的提问来源于stack exchange,提问作者Todd R
相关产品推荐
相关产品推荐

