代码之家  ›  专栏  ›  技术社区  ›  Bozho

Float解析与Double相比结果奇怪

  •  0
  • Bozho  · 技术社区  · 4 年前

    我偶然发现了以下问题。虽然我知道花车和双人都有自己的怪癖,但这听起来很奇怪。有人能解释一下(Java 11)吗?

    System.out.println(Float.valueOf(Float.parseFloat("76028223")).intValue());
    System.out.println(Double.valueOf(Double.parseDouble("76028223")).intValue());
    

    结果:

    76028224
    76028223
    
    0 回复  |  直到 4 年前
        1
  •  8
  •   nanofarad    4 年前

    浮点数使用指数尾数表示法存储(类似于小学教的科学记数法)。可用于存储尾数和指数的位数取决于特定的类型(Java中的float vs double,以及列出的更不寻常的类型) here 以及其他地方)。

    表示数值76028223的一种方法是1.00100010000001001011011111(目前尚未提及任何特定的浮点类型) 2. * 2^26.

    尾数 float 表示24位(23位存储在整数中,一位隐式 1. ),这意味着它不能代表1.00100010000001010011111的所有有效位。尾数需要27位来精确表示。

    相反,我们可以用浮点数做的最好的事情是使用最接近的24位(1.23位)尾数,即1.001000100000010101000(通过对前一个尾数进行四舍五入获得)。这个尾数,加上正确的指数,代表1.001000100000010101000 2. * 2^26 = 76028224.

    例如,这种截断会导致一些意想不到的惊喜 76028223f + 1 == 76028223f 为true(与该浮点文字最接近的表示形式为76028224,76028224+1最接近的浮点表示形式也为76028224)。

    A. double 具有更高的精度,因此具有更大的指数范围+更高的精度尾数(53位,其中52位显式存储),因此它可以精确地表示选定的输入。

    1. “小数点”前的前导位对于非整数总是1- subnormal 浮动,因此不需要存储。