前情

最近在做一个后端需求,需求中需要前端做一些金额数字计算,前端对于小数的计算一直都有精度问题,如0.1+0.2计算的结果并不是0.3,而是0.30000000000000004,于是引入高精度计算库math.js来解决前端计算的精度问题。

坑位

这次做的需求是一个退货扣款的需求,如果用户退回来的商品有磨损或者破坏需要进行扣除押金,但是扣除的金额不能超过押金,如果超过押金那就只能扣除押金的金额,开发中功能一切正常,测试也正常,但是一发布到线上发现无法正常工作,对于押金100的商品我想扣除50,正常来说扣款金额应该是50,但是实际显示扣款100,导致提交时和服务端计算的值进行校验不通过,以致始终无法完成数据提交,测试和我又立马回到测试服自测又是一切正常。

Why?

使用math.js转换或者计算方法计算完的值并不是数字,而是特有的BigNumber对象,当你直接拿对象比较的时候,它会调用对象的valueOf方法转换为字符串做比较,而字符串比较是按位比较大小的,所以‘50’跟’100’比,因为5>1所以’50’大于’100’,关键代码如下,为了好理解其中变量被替换成中文:

...
// 实际扣款金额 违约金+磨损扣款金额,不能大于押金
const actualDeductionAmount = computed(() => {
let total = add(
bignumber(违约金 || 0),
bignumber(扣款金额 || 0)
);
let deposit = bignumber(押金金额 || 0);
if (total > deposit) {
total = deposit;
}
return format(total, { precision: 2, notation: "fixed" });
});
...

为什么测试服是好的了,是因为这种扣款是不可退回的,测一次自己要损失一笔钱,于是测试服配置的商品都是小于1的金额的,首位大小都是0,导致比较结果都是正确的,也就没有测试出来。

简单demo测试地址:JS Bin - Collaborative JavaScript Debugging

解决方案

在做比较时使用math.js提供的转数字方法number进行转换后再执行比较,保证数字与数字的比较就不会有问题。

...
// 实际扣款金额 违约金+磨损扣款金额,不能大于押金
const actualDeductionAmount = computed(() => {
let total = add(
bignumber(违约金 || 0),
bignumber(扣款金额 || 0)
);
let deposit = bignumber(押金金额 || 0);
if (number(total) > number(deposit)) {
total = deposit;
}
return format(total, { precision: 2, notation: "fixed" });
});
...

思考

使用第三方工具库时要细看官方文挡,并确定你按收到的返回值是什么类型,此次使用前确实有浏览官方文挡的,但是个人英文真的很一般,不得不百度搜了一些使用教程,那些简易使用教程并没有明确说明返回的值类型,最近也在偶尔刷英语,希望能提高一些英语,对于程序员会英语还是很有帮助的,同时对于自测的时候应该多考虑一些边界值,此次测试都只测了小数金额而同有测整数,也导致问题一直拖到生产环境,幸好的是没有导致线上什么经济损失,不然就尴尬了。

高精度计算库math.js使用踩坑记的更多相关文章

  1. flask--数据库迁移之连环踩坑记

    flask数据库迁移命令: python manage.py db init python manage.py db migrate python manage.py db upgrade 1.报错: ...

  2. Vue + TypeScript + Element 搭建简洁时尚的博客网站及踩坑记

    前言 本文讲解如何在 Vue 项目中使用 TypeScript 来搭建并开发项目,并在此过程中踩过的坑 . TypeScript 具有类型系统,且是 JavaScript 的超集,TypeScript ...

  3. Spark踩坑记——Spark Streaming+Kafka

    [TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...

  4. 【踩坑记】从HybridApp到ReactNative

    前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. Hy ...

  5. Spring @Transactional踩坑记

    @Transactional踩坑记 总述 ​ Spring在1.2引入@Transactional注解, 该注解的引入使得我们可以简单地通过在方法或者类上添加@Transactional注解,实现事务 ...

  6. Spark踩坑记:Spark Streaming+kafka应用及调优

    前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark streaming从k ...

  7. iOS自动化打包上传的踩坑记

    http://www.cocoachina.com/ios/20160624/16811.html 很久以前就看了很多关于iOS自动打包ipa的文章, 看着感觉很简单, 但是因为一直没有AppleDe ...

  8. [技术博客] 敏捷软工——JavaScript踩坑记

    [技术博客] 敏捷软工--JavaScript踩坑记 一.一个令人影响深刻的坑 1.脚本语言的面向对象 面向对象特性是现代编程语言的基本特性,JavaScript中当然集成了面向对象特性.但是Java ...

  9. WinUI 3 踩坑记:从创建项目到发布

    本文是 WinUI 3 踩坑记 的一部分,该系列发布于 GitHub@Scighost/WinUI3Keng,若内容出现冲突以 GitHub 上的为准. 创建项目 现在 WinUI 3 的入门体验比刚 ...

  10. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

随机推荐

  1. Java读取寄存器数据的方法

    在Java中直接读取硬件寄存器(如CPU寄存器.I/O端口等)通常不是一个直接的任务,因为Java设计之初就是为了跨平台的安全性和易用性,它并不直接提供访问底层硬件的API.不过,在嵌入式系统.工业控 ...

  2. 十五,Spring Boot 整合连接数据库(详细配置)

    十五,Spring Boot 整合连接数据库(详细配置) @ 目录 十五,Spring Boot 整合连接数据库(详细配置) 最后: JDBC + HikariDataSource(Spring Bo ...

  3. 这10种分布式ID,太绝了!

    前言 分布式ID,在我们日常的开发中,其实使用的挺多的. 有很多业务场景在用,比如: 分布式链路系统的trace_id 单表中的主键 Redis中分布式锁的key 分库分表后表的id 今天跟大家一起聊 ...

  4. 普元中间件Primeton AppServer6.5安装(Windows)

    本文在Windows环境下安装普元中间件Primeton AppServer6.5(以下简称PAS) 一.安装前准备 1.1使用软件版本 Primeton_AppServer_6.5_Enterpri ...

  5. 课时05:Linux必备系统命令

  6. 关于Android Q平台上qssi的介绍

    QSSI 是 Qualcomm Single System Image 的缩写. Android Q上开始支持QSSI. QSSI 是用来编译system.img的3.1 QSSI编译注意事项 lun ...

  7. eBPF 概述:第 3 部分:软件开发生态

    1. 前言 在本系列的第 1 部分和第 2 部分中,我们对 eBPF 虚拟机进行了简洁的深入研究.阅读上述部分并不是理解第 3 部分的必修课,尽管很好地掌握了低级别的基础知识确实有助于更好地理解高级别 ...

  8. .Net 的扩展方法

    // 扩展方法 // ps:js中的扩展方法 比如 给数组定义一个自定义的全局的方法 使用 prototype (原型链) // .Net 给 string 添加一些扩展方法 String 是一个密封 ...

  9. ssh建立github连接 基于ssh密钥

    1. 建立公钥和私钥 ps:公钥放在github上面的,私钥放在自己本地电脑 : 先生成密钥:打开 gitbash 输入命令: ssh-keygen -t rsa -b 4096 -C "z ...

  10. manim边做边学--直角平面

    直角平面NumberPlane是Manim库中用于创建二维坐标平面的对象,它可以帮助用户在场景中可视化坐标轴以及网格线. 通过坐标轴.网格线以及刻度,它能够动态地展示函数曲线.几何图形以及它们的变换过 ...