【发布时间】:2020-09-09 12:52:20
【问题描述】:
我正在用 JAVA 中的BigDecimal 制作sin 函数,这就是我目前为止的工作:
package taylorSeries;
import java.math.BigDecimal;
public class Sin {
private static final int cutOff = 20;
public static void main(String[] args) {
System.out.println(getSin(new BigDecimal(3.14159265358979323846264), 100));
}
public static BigDecimal getSin(BigDecimal x, int scale) {
BigDecimal sign = new BigDecimal("-1");
BigDecimal divisor = BigDecimal.ONE;
BigDecimal i = BigDecimal.ONE;
BigDecimal num = null;
BigDecimal result = x;
//System.err.println(x);
do {
x = x.abs().multiply(x.abs()).multiply(x).multiply(sign);
i = i.add(BigDecimal.ONE);
divisor = divisor.multiply(i);
i = i.add(BigDecimal.ONE);
divisor = divisor.multiply(i);
num = x.divide(divisor, scale + cutOff, BigDecimal.ROUND_HALF_UP);
result = result.add(num);
//System.out.println("d : " + divisor);
//System.out.println(divisor.compareTo(x.abs()));
System.out.println(num.setScale(9, BigDecimal.ROUND_HALF_UP));
} while(num.abs().compareTo(new BigDecimal("0.1").pow(scale + cutOff)) > 0);
System.err.println(num);
System.err.println(new BigDecimal("0.1").pow(scale + cutOff));
return result.setScale(scale, BigDecimal.ROUND_HALF_UP);
}
}
它使用泰勒级数: picture of the fomular
每次迭代都会添加单项式x,并且始终为负数。
而问题是,x 的绝对值越来越大,所以迭代永远不会结束。
有没有办法找到它们,或者从一开始就有更好的方法来实现它?
编辑:
我从头开始编写这段代码,只是对三角函数很感兴趣,现在我看到了很多幼稚的错误。
我最初的意图是这样的:num 是 x^(2k+1) / (2k+1)!divisor 是 (2k+1)!i 是 2k+1dividend 是 x^(2k+1)
所以我用i 更新divisor 和dividend 并通过sign * dividend / divisor 计算num 并将其添加到result by result = result.add(num)
所以新的和运行良好的代码是:
package taylorSeries;
import java.math.BigDecimal;
import java.math.MathContext;
public class Sin {
private static final int cutOff = 20;
private static final BigDecimal PI = Pi.getPi(100);
public static void main(String[] args) {
System.out.println(getSin(Pi.getPi(100).multiply(new BigDecimal("1.5")), 100)); // Should be -1
}
public static BigDecimal getSin(final BigDecimal x, int scale) {
if (x.compareTo(PI.multiply(new BigDecimal(2))) > 0) return getSin(x.remainder(PI.multiply(new BigDecimal(2)), new MathContext(x.precision())), scale);
if (x.compareTo(PI) > 0) return getSin(x.subtract(PI), scale).multiply(new BigDecimal("-1"));
if (x.compareTo(PI.divide(new BigDecimal(2))) > 0) return getSin(PI.subtract(x), scale);
BigDecimal sign = new BigDecimal("-1");
BigDecimal divisor = BigDecimal.ONE;
BigDecimal i = BigDecimal.ONE;
BigDecimal num = null;
BigDecimal dividend = x;
BigDecimal result = dividend;
do {
dividend = dividend.multiply(x).multiply(x).multiply(sign);
i = i.add(BigDecimal.ONE);
divisor = divisor.multiply(i);
i = i.add(BigDecimal.ONE);
divisor = divisor.multiply(i);
num = dividend.divide(divisor, scale + cutOff, BigDecimal.ROUND_HALF_UP);
result = result.add(num);
} while(num.abs().compareTo(new BigDecimal("0.1").pow(scale + cutOff)) > 0);
return result.setScale(scale, BigDecimal.ROUND_HALF_UP);
}
}
【问题讨论】:
标签: java math trigonometry