V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
SlanWyf
V2EX  ›  Java

请教大家一个关于 Java 浮点精度的问题

  •  
  •   SlanWyf · 2023-10-21 18:21:17 +08:00 · 1705 次点击
    这是一个创建于 400 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在学习 easyExcel 的时候,发现一个浮点精度丢失的问题 如果属性为 double 类型。往 excel 中写入 19.8 ,excel 中显示的是 19.8 ,再读取,读取到的是 19.799999999999997 如果属性为 String 类型。往 excel 中写入 19.8 ,excel 中显示的是 19.799999999999997 ,再读取,读取到的是 19.799999999999997 ,但如果 excel 中本就是 19.8 ,那么读取到的也是 19.8

    所以初步判断属性为 double ,写入不会错,读取会错;属性为 String ,读取不会错,写入会错

    在网上只可以查到这是由于浮点精度问题,但不知为什么会造成读取与写入的不同,为什么要么写入错,要么读取错,而不是同时错,或同时不错。而且既然属性为 String 为什么还会有浮点精度问题

    第 1 条附言  ·  2023-10-21 22:06:53 +08:00
    好吧,所谓的 String 类型写入会出现异常其实是因为我在录入数据的时候,是通过 double 转为 String 的,那个时候就已经出现异常了,并非 easyExcel 问题。
    9 条回复    2023-10-22 00:49:27 +08:00
    ranaanna
        1
    ranaanna  
       2023-10-21 18:55:45 +08:00
    浮点数是离散的,双精度浮点数的间隔是 10^n*2^(-52) = 2.22e(n-16),是不存在 19.8 这么精确的数的。OP 可以大概算一下双精度浮点数表示 19.8 的误差,已经小到亿亿分之几了吧。所以不明白为什么 OP 会认为读取出错。
    至于为什么 String 还是被当作浮点数,没用过 easyExcel 不知道,这锅不应该 Java 来背
    SlanWyf
        2
    SlanWyf  
    OP
       2023-10-21 19:45:25 +08:00
    @ranaanna 本人是个新人,对于这种原理方面的东西没有了解过。文中我可能没描述清楚,我所说的读取出错只是指,excel 中 19.8 的数字通过 easyExcel 读取到 java 中输出为 19.799999999999997 这种现象。并没有对这种现象尝试做出自己的见解。
    512357301
        3
    512357301  
       2023-10-21 19:53:44 +08:00 via Android
    换个思路,程序写入到 Excel 之后,就不再读取这个文件了。这样就没错了。
    读取的话,只读取用户准备好的 Excel 表。
    还有个办法就是不相信 Excel 的数据,所有的数据都做四舍五入处理(保留 4 位小数),或者用专门的 math 库来处理数据,避免精度问题。
    ranaanna
        4
    ranaanna  
       2023-10-21 19:59:00 +08:00
    @SlanWyf 这是正常现象,并没有出错
    kanezeng
        5
    kanezeng  
       2023-10-21 20:21:19 +08:00
    这个问题不是 Java 浮点精度问题,应该说是 EasyExcel 的问题? EasyExcel 就有过 Issue 吧。可以以 BigDecimal 去读数据,然后以 String 类型写数据。如果要用 String 读写,那就在字段上添加 @NumberFormat 注解
    sumarker
        6
    sumarker  
       2023-10-21 20:41:08 +08:00
    1. 程序里十进制小数数转二进制存在精度损失的问题——这个可以很容易搜到具体情况
    2. easyExcel 在做转换赋值的时候逻辑问题——需要查具体源码
    3. excel 展示的时候,单元格类型问题——这个应该也很容易遇到
    pengtdyd
        7
    pengtdyd  
       2023-10-21 22:11:33 +08:00
    详见 《 IEEE 754 》
    Goooooos
        8
    Goooooos  
       2023-10-21 22:13:43 +08:00 via Android
    这不是 java 的问题,这是计算机二进制表示浮点数的问题
    night98
        9
    night98  
       2023-10-22 00:49:27 +08:00
    这种问题就两个方向,一个是写入之前的数据就已经出错了,一个是写入到 excel 里面没有设置单元格的数据格式导致的读取错误
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2680 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 15:23 · PVG 23:23 · LAX 07:23 · JFK 10:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.