将Long.MAX_VALUE转换为Float

时间:2017-12-14 17:43:26

标签: java binary bit

我很乐意将Integer转换为Float,Float转换为Long,Long转换为Int,然后我对此行为感到困惑。

当我转换表示s(63 1s)的字符串Long.MAX_VALUE时,我得到了NumberFormatException,这是预期的。因为Long是64位而Integer是32位所以有额外的31 1。 (这是我的猜测也许是另一个原因,如果我错了请纠正我)

但是,在将NumberFormatException转换为Long时,我不确定为什么没有FloatLong再次为64位,Float为32位,就像Integer一样。我知道位被解释为Float(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 个答案:

答案 0 :(得分:1)

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

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

long的精确度始终为1。但是,float的精确度取决于数字的大小。

IEEE single-precision floating point number float中,尾数中只有24位精度,或存储的“分数”部分。因此,float表示的实际值是Long.MAX_VALUE的实际值的近似值。

Float.floatToIntBits

正如您所知,Float.floatToIntBits方法产生的位数与原始long位表示不同。

  

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

(剪断)

  

<强>返回:   表示浮点数的位。

此方法不会将转换为int,它只会提供恰好存储在{{1}中的float的位表示形式}}。此int代表的值应与int的值相同。

转换

这些零是浮点数的尾数。 floatlong的实际转换包括找到最高位的符号,找到建立指数的值的大小,并将值的其余部分转换为尾数。

由于float范围内float的精度有限,因此会丢失一些精度。最终结果是Long.MAX_VALUE值略微向上舍入。因为float是2的幂的1,所以向上舍入产生2的幂,其在尾数中显示为全零。

您可以使用Math.ulp(最后一个单位)的数字刻度查看浮点值的精度。

Long.MAX_VALUE

产生

Math.ulp(f)

正如您所看到的,1.09951163E12 float的差异非常大。 (相应的Long.MAX_VALUE的ulp是double。大,但比2048.0的ulp小得多。)但是它与预期的值几乎相差10 < sup> 19 - float的约7位精度。

答案 1 :(得分:0)

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

浮点数的表示方式不同。根据{{​​3}},有问题的数字在Float的范围内。

Java Language Specification

中描述了精确转换,包括舍入

关于`print(Integer.toBinaryString(intBits)); // 1011111000000000000000000000000怎么来的? s是一串1,现在有0?&#39;:

Float.floatToIntBits(f)不会返回&#34;与整数&#34;相同的数字。 它的语义在The JavaDoc

中描述

答案 2 :(得分:0)

float表示在四个字节(32位)上,long表示在8个字节(64位)上。当您将long转换为float时,会丢失一半的数据,因为您无法将64位转换为32位。这就是你丢失很多比特的原因。

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

这就是为什么你能够施放并且施法具有它的结果。