• 请不要在回答技术问题时复制粘贴 AI 生成的内容
mentalidade
V2EX  ›  程序员

js 解析 json 精度丢失怎么处理?

  •  
  •   mentalidade · Oct 31, 2018 · 8678 views
    This topic created in 2936 days ago, the information mentioned may be changed or developed.

    后端保留两位小数,前端显示却丢失了,查了下,是 js 解析 float 精度丢失。不想在后端改成 string,怎么让前端正确显示。

    后端 php 是 float 保留两位小数,转为 json。

        ["money"]=>
        array(3) {
          ["maket_total"]=>
          float(16794.48)
          ["voucher_total"]=>
          string(6) "744.00"
          ["favorable_total"]=>
          float(509.46)
        }
    

    前端接收却是:"money":{"maket_total":16794.48,"voucher_total":"744.00","favorable_total":509.46000000000004}},

    Supplement 1  ·  Nov 1, 2018
    array(4) {
      ["data"]=>
      array(2) {
        ["saled"]=>
        object(Illuminate\Database\Eloquent\Collection)#1235 (1) {
          ["items":protected]=>
          array(0) {
          }
        }
        ["money"]=>
        array(3) {
          ["maket_total"]=>
          float(16794.48)
          ["voucher_total"]=>
          string(6) "744.00"
          ["favorable_total"]=>
          float(509.46)
        }
      }
      ["status"]=>
      int(0)
      ["msg"]=>
      string(12) "操作成功"
      ["total"]=>
      int(0)
    }
    
    php的json_encode()之后:
    string(170) "{"data":{"saled":[],"money":{"maket_total":16794.48,"voucher_total":"744.00","favorable_total":509.46000000000004}},"status":0,"msg":"\u64cd\u4f5c\u6210\u529f","total":0}"
    

    然后json_encode()就丢失精度了

    Supplement 2  ·  Nov 1, 2018
    这是 laravel 框架里的,自己单独写一个文件却没有重现这个问题
    28 replies  •  2022-11-05 21:36:44 +08:00
    TommyLemon
    TommyLemon
    Oct 31, 2018❤️1
    1
    也保留两位小数
    TomatoYuyuko
    TomatoYuyuko
    Oct 31, 2018❤️1
    2
    不了解 php 怎么做的,我这里大概思路是用 string 类型传送浮点数,然后前端再做处理。
    mentalidade
    mentalidade
    OP
    Oct 31, 2018
    3
    @TommyLemon #1
    @TomatoYuyuko #2 我用的 toFixed(2) 解决了
    HanMeiM
    HanMeiM
    Oct 31, 2018❤️1
    4
    一般要么存整数,要么传 string
    lance7in
    lance7in
    Oct 31, 2018❤️1
    5
    string
    mentalidade
    mentalidade
    OP
    Oct 31, 2018
    6
    @HanMeiM #4
    @TomatoYuyuko #2 青门你们也是后端吗?因为是钱得数值,保留两位小数的浮点数。必须要转换为 string 吗?
    micean
    micean
    Oct 31, 2018❤️1
    7
    钱的话谨慎用 toFixed
    HanMeiM
    HanMeiM
    Oct 31, 2018❤️1
    8
    @mentalidade 是后端啊,这里没说是钱啊。其次我们的钱单位为厘,分的更小一位
    SakuraKuma
    SakuraKuma
    Oct 31, 2018❤️1
    9
    钱的话建议传 /存储都是整数不要小数。
    小数只是显示用。

    这浮点数精度无解的
    MrJeff
    MrJeff
    Oct 31, 2018❤️1
    10
    用 string 吧 省事
    westoy
    westoy
    Oct 31, 2018
    11
    小额可以传 long, 末两位做小数, 注意控制溢出

    或者传字符窜, 用 decimal 或者 gmp

    既然不想在后端改, 那就无解了

    浮点一时爽, 会计对账小一半订单有个几毛几分的误差就 happy 了
    TomatoYuyuko
    TomatoYuyuko
    Oct 31, 2018❤️1
    12
    @mentalidade 前端,一般来说前端不处理数据,只负责呈现,没有特别需求保留 2 位小数就好了。
    当然数据库你肯定要存精确的,你可以直接在服务端把数字精确处理后再给前端。或者 string 之后给前端处理。
    js 这类语言对浮点数处理会有误差,尽可能不要让 js 处理小数运算。
    atcdef
    atcdef
    Oct 31, 2018❤️1
    13
    这个无解的,要么前端格式化一下再显示,要么后端传格式化好的字符串来。我一般都是传格式化好的字符串到前端
    8e47e42
    8e47e42
    Oct 31, 2018❤️1
    14
    一般比较容易的是直接传 string,当然也可以选择成本扩大变成 bigint,当然很多库默认都不支持 bigint,然后你懂的,GG,到最后还是变成了传 string 最靠谱。
    sxlzll
    sxlzll
    Oct 31, 2018
    15
    如果是钱,单位可以改成分
    其他的 float,确实比较稳妥的做法是两个字段,data, data_str
    dd112389
    dd112389
    Nov 1, 2018❤️3
    16
    这里有个坑,前些天才遇到过.
    你可以看一下 php 的 json_encode 函数的说明, 里面有写 php.ini 中的一个设置 serialize_precision 会导致 json_encode 的精度丢失问题.
    将这个设置改为 16 以下应该就不会了.
    ini_set('serialize_precision', 15);
    justyue
    justyue
    Nov 1, 2018 via iPhone❤️1
    17
    我司,钱都是转成 string 传的,安全方便
    mentalidade
    mentalidade
    OP
    Nov 1, 2018
    18
    @dd112389 #16 是的,我发现是 json_encode()的问题,但是上面的实际的例子,maket_total 这个值就没事,favorable_total 却发生了精度丢失,明明两个都是保留两位小数的 float ?求解
    weixiangzhe
    weixiangzhe
    Nov 1, 2018
    19
    我司都是整数
    lukunlin
    lukunlin
    Nov 1, 2018
    20
    .toFixed(2)一下就好了啊~
    BBCCBB
    BBCCBB
    Nov 1, 2018
    21
    long 类型 超过 53 还是 54, js 解析也会出问题的, 还是用 string 吧.
    BBCCBB
    BBCCBB
    Nov 1, 2018
    22
    53, 54 位
    promise2mm
    promise2mm
    Nov 1, 2018
    23
    http://www.css88.com/archives/7340#more-7340
    这里有大佬的分析,我司也遇到过
    shuang
    shuang
    Nov 1, 2018
    24
    0.495.toFixed(2)
    "0.49"
    kran
    kran
    Nov 1, 2018 via iPhone
    25
    乘上 10^n 再编码成 json
    zjsxwc
    zjsxwc
    Nov 1, 2018
    26
    php7.1.x 特定小版本的问题,

    加一句
    ```
    ini_set('serialize_precision', -1);
    ```
    就行

    http://php-symfony.uk/json_encode-producing-unexpected-float-values-in-php-7-1/
    msg7086
    msg7086
    Nov 1, 2018
    27
    钱用浮点数这种近似表示法是作大死。只要是近似表示,就会有误差,再怎么都会有。
    Jobing
    Jobing
    Nov 5, 2022
    28
    可以用这个开源库解决: https://github.com/jobinben/json-bn
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1811 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 57ms · UTC 01:26 · PVG 09:26 · LAX 17:26 · JFK 20:26
    ♥ Do have faith in what you're doing.