精度丢失问题

简介: BFF Client 使用的 npm 包 request-promise-native 请求微服务接口返回 ID 精度丢失

6.png


背景


  • BFF Client 使用的 npm 包 request-promise-native 请求微服务接口返回 ID 精度丢失

1713166949059674112 => 1713166949059674000


为什么会丢失?


  • 存储二进制时小数点的偏移量最大为52位,计算机存储的为二进制,而能存储的二进制为62位,超出就会有舍入操作,因此 JS 中能精准表示的最大整数是 Math.pow(2, 53),十进制即9007199254740992大于 9007199254740992 的可能会丢失精度



  • request-promise-native 发起请求时,当options.json 不为 false 会使用 JSON.parse 解析 body


if (self._json) {
  try {
    response.body = JSON.parse(response.body, self._jsonReviver)
  } catch (e) {
    debug('invalid JSON received', self.uri.href)
  }
}


最小 demo


搭建服务 API


一、搭建 Java Web Api:



public long getId() {
        return id + 1713166949059674112L;
    }
* 修改 controller 层添加 post 请求
    @PostMapping("/greeting_create")
    public Greeting createGreeting(@RequestParam(value = "name", defaultValue = "World") String name) {
        return new Greeting(counter.incrementAndGet(), String.format(template, name));
    }


二、请求


  • GET 请求: curl http://localhost:8080/greeting
  • POST 请求:curl -X POST http://localhost:8080/greeting_create


{"id":1713166949059674120,"content":"Hello, World!"}


解决方案


1. 获取响应体的字符串,使用 JSONbigid 转化成字符串


  • 优点:只影响当前请求
  • 缺点:不支持 POST 请求方式,


  • 通过 json 传参数不支持
  • 通过 form + json: false 传参数需要后端接口支持


  • GET 请求


const rp = require('request-promise-native');
const jsonBigInt = require('json-bigint');
  const getOptions = {
    'method': 'GET',
    json: false,
    'url': 'http://localhost:8080/greeting',
  };
  const getRes = await rp(getOptions);
  console.log('get result: ', jsonBigInt.parse(getRes));


  • POST 请求:不支持,json 被占用,一定会执行 JSON.parse


const rp = require('request-promise-native');
const jsonBigInt = require('json-bigint');
  const postOptions = {
    'method': 'POST',
    'url': 'http://localhost:8080/greeting_create',
    json: { name: 'test' },
  };
  const postRes = await rp(postOptions);
  console.log('post result: ', jsonBigInt.parse(postRes));


2. 使用 JSONbig.parse() 替换 JSON.parse()


  • 优点:实现简单,支持 POST
  • 缺点:影响所有的 JSON.parse() 解析


const rp = require('request-promise-native');
const jsonBigInt = require('json-bigint');
async function jsonBigReplaceParse() {
  const oldParse = JSON.parse;
  JSON.parse = jsonBigInt.parse;
  const postOptions = {
    'method': 'POST',
    'url': 'http://localhost:8080/greeting_create',
    json: { name: 'test' },
  };
  const postRes = await rp(postOptions);
  console.log('post result: ', postRes);
  JSON.parse = oldParse;
}


~ 本文完,感谢阅读!


学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!




相关文章
|
20天前
|
存储 监控 算法
在进行精度控制时,如何避免舍入误差的累积?
【10月更文挑战第29天】通过选择合适的精度控制方法、优化计算顺序和方式、运用误差补偿技术以及建立数据验证与监控机制等多种手段的综合运用,可以有效地避免舍入误差的累积,提高计算结果的精度和可靠性,满足各种对精度要求较高的应用场景的需求。
|
3月前
BigDecimal 为什么可以保证精度不丢失?
【8月更文挑战第8天】在软件开发中,尤其是在涉及财务计算、科学计算等领域,确保数值的精度至关重要。然而,传统的浮点数类型(如float和double)在计算过程中往往会遇到精度丢失的问题。这时,BigDecimal 类因其能够精确表示小数点后的数值而备受青睐。下面,我们将深入探讨 BigDecimal 如何保证精度不丢失。
253 2
机器精度
Julia 的 `eps` 函数用于计算浮点数的机器精度,即相邻可表示浮点数间的距离。例如,`eps(Float32)` 为 `1.1920929f-7`,`eps(Float64)` 为 `2.220446049250313e-16`。`eps(x)` 返回 `x` 与下一个浮点数的差值,`nextfloat` 和 `prevfloat` 函数则返回给定值的相邻浮点数。浮点间距在数轴上非均匀分布,靠近零的区域更密集。
|
6月前
LabVIEW为什么浮点数会丢失精度
LabVIEW为什么浮点数会丢失精度
55 2
|
存储 JSON 前端开发
前端接收后端数据时,遇到精度丢失的问题
前端接收后端数据时,遇到精度丢失的问题
1520 0
|
算法 数据挖掘
scanpy数据整合批次效应去除原理
scanpy数据整合批次效应去除原理
|
机器学习/深度学习 传感器 算法
在一定的虚警概率下,检测概率随着信噪比的增大而增大附matlab代码
在一定的虚警概率下,检测概率随着信噪比的增大而增大附matlab代码
|
算法
【计组】32位浮点数的表示范围以及如何解决精度缺失
【计组】32位浮点数的表示范围以及如何解决精度缺失
510 0
【计组】32位浮点数的表示范围以及如何解决精度缺失
|
存储 Java 关系型数据库
100. BigDecimal一定不会丢失精度吗
100. BigDecimal一定不会丢失精度吗
123 0
100. BigDecimal一定不会丢失精度吗