Vue处理超过16位数字精度丢失问题(数字最后两位变0)

当使用MyBatis-Plus的ASSIGN_ID生成19位主键时,前端由于通常只处理16位导致精度丢失。后端可以通过@JsonSerialize注解配合ToStringSerializer处理,前端则可以引入json-bigint库,修改axios的transformResponse来避免精度问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

当我们使用MyBatis-Plus 使用 ASSIGN_ID(雪花算法) 生成的id作为主键时,因为其长度为19位,而前端一般能处理16位,如果不处理的话在前端会造成精度丢失,最后两位会变成00,感觉像是四舍五入后的效果,如下:

1648981853080055810 => 1648981853080055800

后端处理

@JsonSerialize(using = ToStringSerializer.class)
@TableId
private Long id;

前端处理

前端一般都是用axios进行数据请求,我们通过引入json-bigint来解决:

// 安装依赖
npm install json-bigint

// 使用
import JSONBIG from 'json-bigint'

axios.defaults.transformResponse = [
  function (data) {
    const json = JSONBIG({
      storeAsString: true
    })
    const res = json.parse(data)
    return res
  }
]
<think>好的,我现在需要解决用户在Vue3和TypeScript中进行浮点数运算时遇到的精度丢失问题。首先,我得回忆一下为什么浮点数运算会有精度问题。因为计算机使用二进制表示浮点数,有些十进制小数无法精确换为二进制,导致计算时出现舍入误差。比如0.1在二进制中是无限循环的,所以计算0.1 + 0.2可能不会得到精确的0.3。 接下来,用户的环境是Vue3和TypeScript,所以我需要考虑这两种技术栈下的解决方案。首先,常见的处理浮点数精度的方法有哪些呢? 1. 放大为整数计算后再缩小:比如将0.1元为1分进行计算,避免小数运算。这需要将数值乘以10的n次方换为整数,计算后再除以相应的倍数。这种方法简单,但需要处理不同小数的情况,可能有些繁琐。 2. 使用第三方库:比如decimal.js或者big.js,这些库专门处理精度的小数运算。它们通过字符处理或者更精确的算法来避免二进制浮点数的精度问题。这对于复杂的计算比较有效,但会增加项目的依赖。 3. 限制小数数并四舍五入:使用toFixed方法或者在显示时格式化,但这只是表面处理,实际存储的值可能仍有误差,比如用toFixed(2)来显示两位小数。不过要注意,toFixed本身也可能有舍入问题,比如(0.1 + 0.2).toFixed(1)可能得到正确的结果,但复杂的计算仍需谨慎。 4. 自定义工具函数:编写一个处理加减乘除的函数,统一处理精度。这可能结合放大整数和四舍五入的方式,比如将运算换为整数后进行,再恢复小数数。这种方法可以针对项目中的常见运算进行封装,提高代码复用性。 现在考虑TypeScript中的实现,需要确保类型安全。比如在放大整数时,可能需要处理数值类型换,或者使用字符串来处理以避免中间步骤的精度丢失。例如,将数字换为字符串后,分割整数和小数部分,确定需要放大的倍数,然后进行计算。 在Vue3中,可能需要在计算属性或者方法中调用这些处理函数,确保显示的结果正确。比如在模板中显示商品价格时,使用formatCurrency函数来处理精度问题。 然后,需要参考用户提供的引用内容。例如,引用[1]提到隐式换的问题,这可能与parseFloat的处理有关,但用户的问题更多是运算时的精度丢失,而不是字符换。引用[2]中的元组和扩展运算符可能暂时不相关。引用[3]提到的TypeScript优势,如静态类型检查,可能在编写工具函数时帮助检测类型错误。引用[4]中的confirm函数可能与当前问题无关。 所以,可能的解决方案包括: - 推荐使用decimal.js库,因为它提供了精确的十进制运算,并且有TypeScript支持。 - 提供放大整数的方法示例,比如将数值换为整数进行计算,处理加减乘除。 - 在显示时使用toFixed,并提醒注意其局限性。 - 创建一个工具类或函数,统一处理运算,确保在Vue3组件中调用方便。 例如,在TypeScript中,可以编写一个工具模块,包含add、subtract、multiply、divide等方法,每个方法都先将数字换为整数进行计算,然后返回结果。同时,处理小数数的问题,避免中间步骤的精度丢失。 另外,需要注意在Vue3的响应式数据中,如何处理这些运算结果,可能需要使用计算属性来实时更新。 最后,可能需要测试不同的方法,比较它们的优缺点,选择最适合项目需求的方式。如果项目中有大量财务计算,使用decimal.js会更可靠;如果是简单的显示问题,放大整数或四舍五入可能更简便。</think>在Vue3与TypeScript中解决浮点数运算精度丢失问题,可通过以下方案实现: ### 解决方案 #### 1. 数值放大法(整数运算) 将浮点数换为整数进行运算,再缩小回小数: ```typescript // 精度处理工具函数 class PrecisionUtil { // 加法 static add(a: number, b: number): number { const multiple = Math.pow(10, Math.max(this.getDecimalLength(a), this.getDecimalLength(b))) return (a * multiple + b * multiple) / multiple } // 获取小数数 private static getDecimalLength(num: number): number { const str = num.toString() const dotIndex = str.indexOf('.') return dotIndex === -1 ? 0 : str.length - dotIndex - 1 } } ``` 在Vue组件中使用: ```typescript // Component.vue const total = computed(() => PrecisionUtil.add(0.1, 0.2)) // 0.3 ``` #### 2. 使用高精度计算库 推荐使用`decimal.js`库: ```bash npm install decimal.js @types/decimal.js ``` 示例代码: ```typescript import { Decimal } from 'decimal.js' // 精确加法运算 const result = new Decimal(0.1).add(new Decimal(0.2)).toNumber() // 0.3 ``` #### 3. 显示时格式化处理 对最终显示结果进行格式化: ```typescript const formatCurrency = (value: number): string => { return value.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) } ``` ### 方案对比 | 方法 | 优点 | 缺点 | |-------------|--------------------------|--------------------------| | 数值放大法 | 无需依赖第三方库 | 需处理复杂运算逻辑 | | decimal.js | 支持复杂运算,精度可靠 | 增加项目依赖 | | 显示格式化 | 实现简单 | 不改实际存储值 | ### 推荐实践 1. **财务计算**:优先使用`decimal.js`保证计算精度[^3] 2. **简单运算**:采用数值放大法减少依赖 3. **展示层处理**:结合`toFixed()`与正则表达式 ```typescript const formatDecimal = (num: number) => parseFloat(num.toFixed(10)).toString().replace(/(\.\d*?[1-9])0+$/, "$1") ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值