将 Long.MAX_VALUE 转换为浮点数
Convert Long.MAX_VALUE to Float
我通过将 Integer 转换为 Float、Float 转换为 Long、Long 转换为 Int 来玩得很开心,然后我对下面的这种行为感到困惑。
当我转换表示 Long.MAX_VALUE
(63 1s)的字符串 s
时,我得到了预期的 NumberFormatException
。因为 Long
是 64 位,而 Integer
是 32 位,所以多了 31 个 1。 (这是我的猜测,也许是另一个原因,如果我错了请纠正我)
但是我不确定为什么在将 Long
转换为 Float
时没有得到 NumberFormatException
。 Long
也是 64 位,而 Float
是 32 位,就像 Integer
一样。我知道位被不同地解释为 Float
(IEEE 754 浮点 "single format" 位布局)但是所有其他额外的 31 位发生了什么?我真的迷路了....
此外,如何获得 1011111000000000000000000000000
位串 9.223372E18?这些 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);
}
关于print(Float.valueOf(s)); //prints 9.223372E18 Why no NumberFormatException? and how did it result 9.223372E18?
:
浮点数的表示方式不同。根据Java Language Specification.
,有问题的数字在Float范围内
中描述了精确转换,包括舍入
关于`print(Integer.toBinaryString(intBits)); //1011111000000000000000000000000 怎么来的? s 是一个由 1 组成的字符串现在有 0 了吗?':
Float.floatToIntBits(f)
不 return "the same number as integer"。
它的语义在 The JavaDoc
中描述
一个float
用四个字节(32位)表示,一个long
用8个字节(64位)表示。当您将 long
转换为 float
时,您会丢失一半数据,因为您无法将 64 位转换为 32 位。这就是你丢失了很多位的原因。
float
使用 23 位尾数,因此大于 2^23 的整数将被截断。
这就是为什么你能够施法并且施法有结果的原因。
首先,让我们确认一下转换是否正确。
Long.MAX_VALUE
是 9223372036854775807(19 位数字)。如您所见,该值大约是您打印的值:9.223372E18
.
long
的精度总是 1
。但是,float
的精度取决于数字的大小。
在一个IEEE single-precision floating point number中,也就是float
,尾数只有24位精度,也就是存储的"fraction"部分。所以 float
表示的实际值是 Long.MAX_VALUE
.
实际值的近似值
Float.floatToIntBits
如您所知,Float.floatToIntBits
方法产生的位与原始 long
位表示不同。
Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "single format" bit layout.
Bit 31 (the bit that is selected by the mask 0x80000000) represents the sign of the floating-point number. Bits 30-23 (the bits that are selected by the mask 0x7f800000) represent the exponent. Bits 22-0 (the bits that are selected by the mask 0x007fffff) represent the significand (sometimes called the mantissa) of the floating-point number.
(剪断)
Returns:
the bits that represent the floating-point number.
此方法不会将值转换为int
,它只给出恰好存储的float
的位表示在 int
中。此 int
表示的值是 而不是 预期与 float
.
的值相同
转换
那些零是浮点数的尾数。 long
到 float
的实际转换涉及找到最高有效位的符号,找到值的大小以建立指数,并将其余值转换为尾数。
由于 float
在 Long.MAX_VALUE
尺度下的精度有限,因此会损失一些精度。最终结果是 float
值略微向上舍入。因为 Long.MAX_VALUE
是 2 的幂减 1,向上舍入产生 2 的幂,在尾数中显示为全零。
您可以在Math.ulp
(单位在最后一位)的数字范围内查看浮点值的精度。
Math.ulp(f)
产生
1.09951163E12
如您所见,float
与 Long.MAX_VALUE
的差异相当大。 (对应的double
的ulp是2048.0
。大了,但是比这里的float
的ulp小很多。)不过符合预期,差不多1019 -- float
.
的精度约为 7 位
我通过将 Integer 转换为 Float、Float 转换为 Long、Long 转换为 Int 来玩得很开心,然后我对下面的这种行为感到困惑。
当我转换表示 Long.MAX_VALUE
(63 1s)的字符串 s
时,我得到了预期的 NumberFormatException
。因为 Long
是 64 位,而 Integer
是 32 位,所以多了 31 个 1。 (这是我的猜测,也许是另一个原因,如果我错了请纠正我)
但是我不确定为什么在将 Long
转换为 Float
时没有得到 NumberFormatException
。 Long
也是 64 位,而 Float
是 32 位,就像 Integer
一样。我知道位被不同地解释为 Float
(IEEE 754 浮点 "single format" 位布局)但是所有其他额外的 31 位发生了什么?我真的迷路了....
此外,如何获得 1011111000000000000000000000000
位串 9.223372E18?这些 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);
}
关于print(Float.valueOf(s)); //prints 9.223372E18 Why no NumberFormatException? and how did it result 9.223372E18?
:
浮点数的表示方式不同。根据Java Language Specification.
,有问题的数字在Float范围内 中描述了精确转换,包括舍入关于`print(Integer.toBinaryString(intBits)); //1011111000000000000000000000000 怎么来的? s 是一个由 1 组成的字符串现在有 0 了吗?':
Float.floatToIntBits(f)
不 return "the same number as integer"。
它的语义在 The JavaDoc
一个float
用四个字节(32位)表示,一个long
用8个字节(64位)表示。当您将 long
转换为 float
时,您会丢失一半数据,因为您无法将 64 位转换为 32 位。这就是你丢失了很多位的原因。
float
使用 23 位尾数,因此大于 2^23 的整数将被截断。
这就是为什么你能够施法并且施法有结果的原因。
首先,让我们确认一下转换是否正确。
Long.MAX_VALUE
是 9223372036854775807(19 位数字)。如您所见,该值大约是您打印的值:9.223372E18
.
long
的精度总是 1
。但是,float
的精度取决于数字的大小。
在一个IEEE single-precision floating point number中,也就是float
,尾数只有24位精度,也就是存储的"fraction"部分。所以 float
表示的实际值是 Long.MAX_VALUE
.
Float.floatToIntBits
如您所知,Float.floatToIntBits
方法产生的位与原始 long
位表示不同。
Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "single format" bit layout. Bit 31 (the bit that is selected by the mask 0x80000000) represents the sign of the floating-point number. Bits 30-23 (the bits that are selected by the mask 0x7f800000) represent the exponent. Bits 22-0 (the bits that are selected by the mask 0x007fffff) represent the significand (sometimes called the mantissa) of the floating-point number.
(剪断)
Returns: the bits that represent the floating-point number.
此方法不会将值转换为int
,它只给出恰好存储的float
的位表示在 int
中。此 int
表示的值是 而不是 预期与 float
.
转换
那些零是浮点数的尾数。 long
到 float
的实际转换涉及找到最高有效位的符号,找到值的大小以建立指数,并将其余值转换为尾数。
由于 float
在 Long.MAX_VALUE
尺度下的精度有限,因此会损失一些精度。最终结果是 float
值略微向上舍入。因为 Long.MAX_VALUE
是 2 的幂减 1,向上舍入产生 2 的幂,在尾数中显示为全零。
您可以在Math.ulp
(单位在最后一位)的数字范围内查看浮点值的精度。
Math.ulp(f)
产生
1.09951163E12
如您所见,float
与 Long.MAX_VALUE
的差异相当大。 (对应的double
的ulp是2048.0
。大了,但是比这里的float
的ulp小很多。)不过符合预期,差不多1019 -- float
.