代码之家  ›  专栏  ›  技术社区  ›  OLIVER.KOO

转换长。最大浮点数

  •  5
  • OLIVER.KOO  · 技术社区  · 7 年前

    我在把整数转换成浮点、浮点转换成Long、Long转换成Int的过程中玩得很开心,然后我被下面的行为弄糊涂了。

    当我转换字符串时 s 代表 Long.MAX_VALUE (63 1s)我有一个 NumberFormatException 这是意料之中的。因为 Long 是64位和 Integer 是32位,因此有额外的31个1。(这是我的猜测,可能是另一个原因,如果我错了,请纠正我)

    然而,我不知道为什么我没有得到 数字格式异常 转换时 长的 Float . 长的 同样是64位和 浮动 32位就像 整数 . 我知道比特被不同的解释为 浮动 (IEEE 754浮点“单格式”位布局)但其他所有额外的31位发生了什么?我在这里真的迷路了。。。。

    此外,如何获得9.223372E18 1011111000000000000000000000000 位字符串?那些0来自哪里?

    public static void main(String[] args){
        String s = String.valueOf(Long.MAX_VALUE); 
        print(s); //prints 9223372036854775807
        print(Long.toBinaryString(Long.MAX_VALUE)); //prints 111111111111111111111111111111111111111111111111111111111111111
        //Integer.valueOf(s) this throws NumberFormatException because Long is 64 bits and Integer is 32 so s is too large to be an Integer
        print(Float.valueOf(s)); //prints 9.223372E18 Why no NumberFormatException? and how did it result 9.223372E18?
    
        float f = Float.valueOf(s);
        int intBits = Float.floatToIntBits(f); 
        print(Integer.toBinaryString(intBits)); //1011111000000000000000000000000 How come? s was a String of 1s now there are 0s?
    }
    
    public static <T> void print(T arg){
        System.out.println(arg);
    } 
    
    3 回复  |  直到 7 年前
        1
  •  1
  •   rgettman    7 年前

    首先,让我们为您确认转换是正确的。

    Long.MAX_VALUE is 9223372036854775807(19位)。如您所见,该值与您打印的值大致相同: 9.223372E18 .

    a的精度 long 始终是 1 . 但是 float 取决于数量的大小。

    在一个 IEEE single-precision floating point number 哪一个 浮动 也就是说,尾数或存储的“分数”部分中只有24位精度。因此 浮动 是实际值的近似值off 长的最大\u值 .

    浮动浮点输入位

    如你所知 Float.floatToIntBits 方法生成的位与原始位不同 长的 位表示法。

    根据IEEE 754浮点“单格式”位布局返回指定浮点值的表示形式。 位31(掩码0x8000000选择的位)表示浮点数的符号。位30-23(由掩码0x7f800000选择的位)表示指数。位22-0(掩码0x007fffff选择的位)表示浮点数的有效位(有时称为尾数)。

    (剪断)

    退换商品 : 表示浮点数的位。

    此方法不会将其转换为 价值 int ,它只给出 浮动 恰好存储在 内景 . 此 内景 预期值与 浮动 .

    转换

    这些零是浮点数的尾数。的实际转换 长的 浮动 包括查找最高有效位的符号,查找值的大小以建立指数,并将其余值转换为尾数。

    因为 浮动 规模为 长的最大\u值 受到限制,某些精度会丢失。最终结果是 浮动 值略微向上舍入。因为 长的最大\u值 如果1缺少2的幂,则取整得到2的幂,它在尾数中显示为全零。

    可以通过以下方式查看数字刻度处的浮点值的精度 Math.ulp (单位位于最后一位)。

    Math.ulp(f)
    

    由此产生

    1.09951163E12
    

    正如您所看到的,对于 浮动 对于 长的最大\u值 . (对应的ulp double 2048.0 . 大,但比ulp小得多 浮动 此处。)但这与预期值接近10的值一致 19 --a的精度约为7位数 浮动 .

        2
  •  0
  •   Lajos Arpad    7 年前

    A. float 以四个字节(32位)表示 long 以8字节(64位)表示。当您转换 长的 到a 浮动 ,则会丢失一半数据,因为无法将64位转换为32位。这就是您丢失了很多位的原因。

    浮动 使用23位尾数,因此大于2^23的整数将被截断。

    这就是为什么你能够施法,并且施法有结果。

        3
  •  0
  •   Yoav Gur    7 年前

    关于 print(Float.valueOf(s)); //prints 9.223372E18 Why no NumberFormatException? and how did it result 9.223372E18? :

    浮点数的表示方式不同。根据 Java Language Specification .

    中介绍了包括舍入在内的精确转换 The JavaDoc

    关于` print(Integer.toBinaryString(intBits))//10111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000?s是由1组成的字符串,现在有0了吗?':

    Float.floatToIntBits(f) 不返回“与整数相同的数字”。 其语义如中所述 The JavaDoc