package test; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class CaculateE { final static int num=17; public static void main(String[] args) { // TODO Auto-generated method stub //使用线程池防止多条人物提交而创建的线程 ExecutorService executor=Executors.newFixedThreadPool(1); Callable<BigDecimal> callable=new Callable<BigDecimal>() { @Override public BigDecimal call() throws Exception { // TODO Auto-generated method stub //舍位模式,四舍五入,100为e的精度上限 MathContext mc=new MathContext(100,RoundingMode.HALF_UP); BigDecimal result=BigDecimal.ZERO; //e=1/0!+1/1!+1/2!+1/3!+...+... for(int i=0;i<num;i++) { //factory()表示阶乘的结果 new BigDecimal() 确保结果精确,防止精度丢失 BigDecimal factorial=factory(new BigDecimal(i)); System.out.println("factorial:"+factorial); //1除以factorial的阶乘 BigDecimal res=BigDecimal.ONE.divide(factorial,mc); System.out.println("res:"+res); result=result.add(res); System.out.println("result:"+result); } return result; } //不用该方法进行转换会报执行异常 private BigDecimal factory(BigDecimal n) { // TODO Auto-generated method stub System.err.println("n的值为:"+n); if(n.equals(BigDecimal.ZERO)) { return BigDecimal.ONE; } else { //subtract(n.subtract(BigDecimal.ONE)) 对象中的值相减 return n.multiply(factory(n.subtract(BigDecimal.ONE)));} } }; //提交一个runable任务进行执行,同时返回一个代表此任务的Future实例 Future<BigDecimal> taskFuture =executor.submit(callable); try { //判断任务是否完成,模拟任务执行,未完成输出waiting,完成之后直接输出结果 while(!taskFuture.isDone()) System.out.println("waiting/"); //线程执行之后可以获取结果 //Callable接口代表一段可以调用并返回结果的代码;Future接口表示异步任务,是还没有完成的任务给出的未来结果。所以说Callable用于产生结果,Future用于获取结果。 System.out.println("taskFuture的get()方法"+taskFuture.get()); }catch(ExecutionException e){ System.err.println("哦豁,抛出执行异常了!"); }catch (InterruptedException ie) { // TODO Auto-generated catch block ie.printStackTrace(); System.err.println("interrupted while waiting"); } executor.shutdown(); } }
代码执行流程:
main()方法调用Excutors的newFixedThreadPool方法获取一个executor.之后初始化实现了Callable接口的匿名类并且将这个任务提交给executor,在返回接收一个Future的实例。
通过isDone()判断是否执行完毕,’waiting‘表示一直在执行,当执行完毕,直接通过 taskFuture.get()获取计算的结果。
阶乘求值过程(包含一个递归):
return n.multiply(factory(n.subtract(BigDecimal.ONE)));例如:5*factory(4) =>5*4*factory(3) =>5*4*3*factory(2) =>5*4*3*2*factory(1) =>5*4*3*2*1*factory(0) =>120
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | ... | 16 |
返回值 | factor(0) | 1*factory(0) | 2*factory(1) | 3*factory(2) | 4*factory(3) | 5*factory(4) | 6*factory(5) | ... | 16*factory(15) |
factorial | factory(0) | 1*factory(0) | 2*1*factory(0) | 3*2*1*factory(0) | 4*3*2*factory(0) | 5*4*3*2*factory(0) | 6*5*4*3*2*factory(0) | ... | 16*15*..*2*factory(0) |
factorial | 1 | 1 | 2 | 6 | 12 | 60 | 120 | ... | 16*15*..*2*factory(0) |
res | 1/1 | 1/1+1/1 | 1/1+1/1+1/2 | 1/1+1/1+1/2+1/6 | 1/1+1/1+1/2+1/6+1/12 | 1/1+1/1+1/2+1/6+1/12+1/60 | 1/1+1/1+1/2+1/6+1/12+1/60+1/120 | ... | 1/1+...+1/16*15*..*2*1 |
ps:增加精度和num的值以求更长的收敛时间和更为接近的e