windows - Java高精度运算问题求助
问题描述
公司项目里面需要做大量的高精度运算,刚开始用double类型运算,后来发现用double类型运算后有些值的精确度超过了理想范围,就用了BigDecimal来计算,现在的问题是BigDecimal的运算效率比double慢几十倍,数据量大的话,慢的要死。请问有没有好的解决方案?这个问题急需解决。
//相关性系数计算public BigDecimal getRelativityTool_bydim(RelativityTool u) {BigDecimal sim = new BigDecimal('0'); //最后的皮尔逊相关度系数BigDecimal common_items_len = new BigDecimal(this.rating_map_list.size()); //操作数的个数BigDecimal this_sum = new BigDecimal('0'); //第一个相关数的和BigDecimal u_sum = new BigDecimal('0'); //第二个相关数的和BigDecimal this_sum_sq = new BigDecimal('0'); //第一个相关数的平方和BigDecimal u_sum_sq = new BigDecimal('0'); //第二个相关数的平方和BigDecimal p_sum = new BigDecimal('0'); //两个相关数乘积的和for (int i = 0; i < this.rating_map_list.size(); i++) { BigDecimal this_grade = this.rating_map_list.get(i); BigDecimal u_grade = u.rating_map_list.get(i); //评分求和 //平方和 //乘积和 this_sum = this_sum.add(this_grade); u_sum = u_sum.add(u_grade); this_sum_sq = this_sum_sq.add(this_grade.pow(2)); u_sum_sq = u_sum_sq.add(u_grade.pow(2)); p_sum = p_sum.add(this_grade.multiply(u_grade));}BigDecimal num = common_items_len.multiply(p_sum).subtract(this_sum.multiply(u_sum));BigDecimal den = sqrt(common_items_len.multiply(this_sum_sq).subtract(this_sum.pow(2)).multiply(common_items_len.multiply(u_sum_sq).subtract(u_sum.pow(2))));if (den.compareTo(new BigDecimal('0')) == 0) { sim = new BigDecimal('1');} else { sim = num.pide(den,5, BigDecimal.ROUND_HALF_UP);}return sim; } //大数字开方 public static BigDecimal sqrt(BigDecimal x) {BigDecimal n1 = BigDecimal.ONE;BigDecimal ans = BigDecimal.ZERO;while ((n1.multiply(n1).subtract(x)).abs().compareTo(BigDecimal.valueOf(0.001)) == 1) { BigDecimal s1 = x.pide(n1, 2000, BigDecimal.ROUND_HALF_UP); BigDecimal s2 = n1.add(s1); n1 = s2.pide(BigDecimal.valueOf(2), 2000, BigDecimal.ROUND_HALF_UP);}ans = n1;BigDecimal rt = new BigDecimal(ans.toString().split('.')[0]);return rt; }
问题解答
回答1:除了使用C或者C++来做高精度运算之外,好像没有什么办法可以同时兼顾性能和精度了。
回答2:大学计算机专业有门课程叫“计算方法”,专门探讨如何在精度有限的计算过程中保持误差最小化。楼主有兴趣的话可以找下相关教材。
回答3:后来发现用double类型运算后有些值的精确度超过了理想范围是超过还是满足不了?
这里有一段计算平方根的代码,我从stackoverflow上找到的,在我自己的机子测试要比你上面那个快十倍左右。所以: 一则你可以通过改进的算法来提高性能,其二,最好的办法找一些已有的library来直接用:例如这个上面列的
public void test_sqrt() { BigDecimal x = BigDecimal.valueOf(Long.MAX_VALUE); BigDecimal x0 = BigDecimal.ZERO; BigDecimal x2 = new BigDecimal(2); BigDecimal x1 = new BigDecimal(Math.sqrt(x.doubleValue())); while (!x0.equals(x1)) {x0 = x1;x1 = x.pide(x0, 2000, BigDecimal.ROUND_HALF_UP);x1 = x1.add(x0);x1 = x1.pide(x2, 2000, BigDecimal.ROUND_HALF_UP); } assertEquals(3037000499L, x1.longValue());}
相关文章:
1. javascript - fis3使用MD5但是如何引用?2. 网页爬虫 - python爬虫翻页问题,请问各位大神我这段代码怎样翻页,还有价格要登陆后才能看到,应该怎么解决3. javascript - JAVA写的H5页面能否解释一下流程4. css - 怎么实现一个圆点在一个范围内乱飞5. python 计算两个时间相差的分钟数,超过一天时计算不对6. javascript - 使用form进行页面跳转,但是很慢,如何加一个Loading?7. docker-machine添加一个已有的docker主机问题8. docker-compose中volumes的问题9. angular.js - 输入邮箱地址之后, 如何使其自动在末尾添加分号?10. javascript - 后台管理系统左侧折叠导航栏数据较多,怎么样直接通过搜索去定位到具体某一个菜单项位置,并展开当前菜单
