js精度问题

1、问题场景:请求接口取得Number类型的数字和后端实际值不一致

比如:
后端返回10976458979374929,实际从接口拿到的是10976458979374928,在控制台也会得到这样的结果:
在这里插入图片描述
原因:

在JavaScript中,Number类型范围-2^53 + 1 到 2^53 - 1 。
ES6引入了Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。
可以用Number.isSafeInteger()用来判断一个整数是否落在这个范围之内
附:在Java中Long类型的取值范围是-2^63 + 1 到 2^63 - 1,比js处理数字范围大的多

解决方案:
  • 后端解决:
    方式1: 修改数据库存的类型为字符串
    方式2:返回接口时转为字符串类型给前端
  • 前端解决: response里转为字符串
    方式1:正则替换
axios({  
	method: method,  
	url: url,  
	data: data,  
	transformResponse: [function (data) {  
	    // 将Long类型数据转换为字符串
	    const convertedJsonString = data.replace(/"(\w+)":(\d{15,})/g, '"$1":"$2"'); 
	    return JSON.parse(convertedJsonString);  
	}],  
})
// 假设后端返回的JSON数据如下:
const responseData = {
  id: 12345678901234567890, // 这是一个Long类型数据
  name: "John Doe"
};
// 处理过的json数据
console.log(responseData.id); // 这将输出字符串:"12345678901234567890"
console.log(typeof responseData.id); // 这将输出 "string"

方式2:json序列化处理

//借助json-bigint这个第三方包来处理
import JSONbig from "json-bigint";
axios({  
	method: method,  
	url: url,  
	data: data,  
	transformResponse: [function (data) {  
		const JSONbigToString = JSONbig({ storeAsString: true });
		// 将Long类型数据转换为字符串
		return JSONbigToString.parse(data);  
	}],  
})
// 假设后端返回的JSON数据如下:
const responseData = {
	id: 12345678901234567890, // 这是一个Long类型数据
	name: "John Doe"
};
// 处理过的json数据
console.log(responseData.id); // 这将输出字符串:"12345678901234567890"
console.log(typeof responseData.id); // 这将输出 "string"

2、常用处理js精度缺失的第三方包

number-precision
主要方法:加减乘除(plus,minus,times, divides)以及求相近值(strip, round)

import NP from 'number-precision';

NP.plus(num1, num2, num3, ...)   //  num + num2 + num3
NP.minus(num1, num2, num3, ...)  //  num1 - num2 - num3
NP.times(num1, num2, num3, ...)  //  num1 * num2 * num3
NP.divide(num1, num2, num3, ...) // num1 / num2 / num3
NP.strip(num)         // 取整
NP.round(num, ratio)  // 四舍五入

你可能感兴趣的:(javascript,ecmascript)