在 Java 中键入转换。加倍到长
Type casting in Java. Double to long
为什么 System.out.println((long)Math.pow(2,63));
和 System.out.println((long)(Math.pow(2,63)-1));
在 Java 中的输出相同?
你应该使用括号来合并结果然后减去 1,像这样:
System.out.println((long)Math.pow(2,63));
System.out.println(((long)(Math.pow(2,63))-1));
输出:
9223372036854775807
9223372036854775806
输出相同,因为 double
没有足够的位来准确表示 263。
一个double
的尾数只有52位:
这最多为您提供 17 位十进制数字的精度。另一方面,您计算的值是 9223372036854775808,因此需要 19 位数字才能准确表示。结果,263 的实际表示为 9223372036854776000:
- 尾数设置为1.0(隐含前面1)
- 指数设置为 1086(隐式减去 1024 得到 63)
1
表示的尾数相同,而有效值为零时指数为1024,即两个数的指数相差63,大于尾数.
当您的数字表示为 double
时会减去 1。由于被减数的量级远大于减数的量级,所以整个减法运算被忽略
减去更大的数字后您会得到相同的结果 - 一直到 512,即 29 (demo)。之后指数的差异将小于 52,因此您将开始得到不同的结果。
对于java中的long数据类型,最大值为9,223,372,036,854,775,807(含)。 (2^63 -1)
所以即使你尝试
System.out.println((long)Math.pow(2,65));
System.out.println((long)(Math.pow(2,63)-1));
输出
9223372036854775807
9223372036854775807
Math.pow( double, double )
returns 个 double
值。
double
in java 是 64 位 IEEE 754 浮点数。(https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html)
如果你看这里:https://en.wikipedia.org/wiki/Double-precision_floating-point_format 你会发现,这个格式由:
- 1 位符号
- 11 位指数
- 53 位有效精度
pow
返回的数字需要更高的精度 (63) 才能准确存储。
基本上您添加的 1
低于此精度阈值。
相比之下,long 具有 64 位精度。
为了更清楚,假设我们使用的是十进制而不是 base2:
在一些假想的精度为 2
的小型浮点数据类型中,值 1000 将存储为 1.00e3
。如果您加 1,则必须将其存储为 1.001e3。但是因为我们只有 2 的精度,它只能存储 1.00e3
并且没有任何变化。所以1.00e3 + 1 == 1.00e3
在您的示例中也会发生同样的情况,只是我们处理的是更大的数字和 base2 的原因。
为什么 System.out.println((long)Math.pow(2,63));
和 System.out.println((long)(Math.pow(2,63)-1));
在 Java 中的输出相同?
你应该使用括号来合并结果然后减去 1,像这样:
System.out.println((long)Math.pow(2,63));
System.out.println(((long)(Math.pow(2,63))-1));
输出:
9223372036854775807
9223372036854775806
输出相同,因为 double
没有足够的位来准确表示 263。
一个double
的尾数只有52位:
这最多为您提供 17 位十进制数字的精度。另一方面,您计算的值是 9223372036854775808,因此需要 19 位数字才能准确表示。结果,263 的实际表示为 9223372036854776000:
- 尾数设置为1.0(隐含前面1)
- 指数设置为 1086(隐式减去 1024 得到 63)
1
表示的尾数相同,而有效值为零时指数为1024,即两个数的指数相差63,大于尾数.
当您的数字表示为 double
时会减去 1。由于被减数的量级远大于减数的量级,所以整个减法运算被忽略
减去更大的数字后您会得到相同的结果 - 一直到 512,即 29 (demo)。之后指数的差异将小于 52,因此您将开始得到不同的结果。
对于java中的long数据类型,最大值为9,223,372,036,854,775,807(含)。 (2^63 -1)
所以即使你尝试
System.out.println((long)Math.pow(2,65));
System.out.println((long)(Math.pow(2,63)-1));
输出
9223372036854775807
9223372036854775807
Math.pow( double, double )
returns 个 double
值。
double
in java 是 64 位 IEEE 754 浮点数。(https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html)
如果你看这里:https://en.wikipedia.org/wiki/Double-precision_floating-point_format 你会发现,这个格式由:
- 1 位符号
- 11 位指数
- 53 位有效精度
pow
返回的数字需要更高的精度 (63) 才能准确存储。
基本上您添加的 1
低于此精度阈值。
相比之下,long 具有 64 位精度。
为了更清楚,假设我们使用的是十进制而不是 base2:
在一些假想的精度为 2
的小型浮点数据类型中,值 1000 将存储为 1.00e3
。如果您加 1,则必须将其存储为 1.001e3。但是因为我们只有 2 的精度,它只能存储 1.00e3
并且没有任何变化。所以1.00e3 + 1 == 1.00e3
在您的示例中也会发生同样的情况,只是我们处理的是更大的数字和 base2 的原因。