事件背景
最近也就上个月吧,拿到一个新的需求,新建一个页面,三个Grid联动,涉及很多的页面和sql以及Java计算。
简略的画个表格表示一下:
第一个Grid:
第二个Grid:
第三个Grid:
业务流程
数量是不可变的,单价是可以修改的,然后在计算规则里选择按比例的话就输入个比值,输入后页面的应收就跟着变化,第三个Grid中的数值也跟着变。
开发思路
第一个版本中,使用sql计算,在页面渲染,每次修改都要保存到数据库后再次查询得到新的计算结果(被否定了,频繁地数据库交互效率低,体验也不好);
第二个版本中,第一个Grid行计算在sql中进行,汇总计算在前端使用框架api;第三个Grid是在每次保存时,通过sql计算第一个Grid的总和插入到第三个Grid查询的表里,然后在单表查询到页面。这是就出现了第一个Grid页面总合计与第三个Grid的页面总合计对不上的情况,每次差别也不大,就0.01左右;后来又增加了一个新的展示框,内容是折前总金额和折后总金额的比值。
问题描述
1> 页面中第一个Girid计算使用的使用parseFloa(数量)parseFloat(单价)parseFloat(折扣比例)的计算方式,结果值在toFixed(2);
新展示框使用 折后总金额/折前总金额 * 100 最后toFixed(2);
2> Java代码中使用BigDecimal的乘除法进行与JS相同的运算;
3> 数据库中使用ROUND(数量单价折扣/100,2)进行计算
现象
页面JS计算与Orcale的差异
(2168.91*0.50*0.78).toFixed(2);
(2167*0.03*3.8).toFixed(2);
SELECT ROUND(2168.91*0.50*0.78,2) FROM DUAL
SELECT ROUND(2167*0.03*3.8,2) FROM DUAL
页面js计算与Java的差异
(1531817.29/10789997.6*100).toFixed(6)
BigDecimal c = new BigDecimal("1531817.29").multiply(new BigDecimal("100").divide(new BigDecimal("10789997.6"),6, RoundingMode.HALF_EVEN));
这里的问题主要在于乘法后的括号问题,修改后的Java代码
BigDecimal c1 = new BigDecimal("1531817.29").multiply(new BigDecimal("100")).divide(new BigDecimal("10789997.6"),6, RoundingMode.HALF_EVEN);
此时JS和Java结果值是一致的,在这里我有个疑问,BigDecimal中的乘除法为什么和传统的数学中的不同呢?
public static void main(String[] args) {String aS = "10789997.6";String bS = "1531817.29";BigDecimal a = new BigDecimal(aS);BigDecimal b = new BigDecimal(bS);BigDecimal c = b.multiply(new BigDecimal("100")).divide(a,6, RoundingMode.HALF_EVEN);BigDecimal c1 = b.multiply(new BigDecimal("100").divide(a,6, RoundingMode.HALF_EVEN));float f1 = new Float(aS);float f2 = new Float(bS);float f3 = f2 * 100 / f1;float f4 = f2 * (100 / f1);System.out.println(c);System.out.println(c1);System.out.println(f3);System.out.println(f4);}
结果对应的是:
14.196642
13.78635561
14.196641
14.19664
结果
最终没有找到JS和Oracle中做到计算结果一致的方法,只能实现到第一次查询时第一个Grid的汇总和第三个Grid的汇总是一致的,因为他们都来自数据库的计算,页面保证每次重新计算完成后是一致的,也就是页面和数据库各自算各自的;BigDecimal的乘除法问题依旧没有想明白,有没有大佬给解释啥为什么会出现括号换个位置结果就差距很大的问题。
顺便吐槽下开发用的前端框架,官网域名都注销了,Api都靠看别的页面代码猜,最奇葩的就是它只支持IE5,换成IE7就页面混乱,开发中时不时的页面就崩了,有时候你刚打开页面,点击查询的那一刻,页面已经无响应了,业务不难,难的是压制住随时想爆发的怒火!
找工作时,找个使用通用的技术,不然你会相当的难受!