Joh*_*ice 8 java double int casting
我试图找出一些非常奇怪的Java行为.我有一个涉及double的公式,但是"保证"给出一个整数答案 - 具体来说,是一个无符号的32位整数(唉,Java不能很好).不幸的是,我的答案有时不正确.
最后,我发现了问题,但其行为仍非常奇怪的对我说:一double,直接投给一个int似乎在被加盖MAX_INT了一个有符号整数,而double要转换成long被然后转换为一个int给了我预期的应答( -1;无符号32位整数的MAX INT,表示为带符号的32位整数).
我写了一个小测试程序:
public static void main(String[] args) {
// This is the Max Int for a 32-bit unsigned integer
double maxUIntAsDouble = 4294967295.00;
long maxUintFromDoubleAsLong = (long)maxUIntAsDouble;
long maxUintFromDoubleAsInt = (int)maxUIntAsDouble;
int formulaTest = (int) (maxUintFromDoubleAsLong * 1.0);
int testFormulaeWithDoubleCast = (int)((long) (maxUintFromDoubleAsLong * 1.0));
// This is a more-or-less random "big number"
long longUnderTest = 4123456789L;
// Max int for a 32-bit unsigned integer
long longUnderTest2 = 4294967295L;
int intFromLong = (int) longUnderTest;
int intFromLong2 = (int) longUnderTest2;
System.out.println("Long is: " + longUnderTest);
System.out.println("Translated to Int is:" + intFromLong);
System.out.println("Long 2 is: " + longUnderTest2);
System.out.println("Translated to Int is:" + intFromLong2);
System.out.println("Max UInt as Double: " + maxUIntAsDouble);
System.out.println("Max UInt from Double to Long: " + maxUintFromDoubleAsLong);
System.out.println("Max UInt from Double to Int: " + maxUintFromDoubleAsInt);
System.out.println("Formula test: " + formulaTest);
System.out.println("Formula Test with Double Cast: " + testFormulaeWithDoubleCast);
}
Run Code Online (Sandbox Code Playgroud)
当我运行这个小程序时,我得到:
Long is: 4123456789
Translated to Int is:-171510507
Long 2 is: 4294967295
Translated to Int is:-1
Max UInt as Double: 4.294967295E9
Max UInt from Double to Long: 4294967295
Max UInt from Double to Int: 2147483647
// MAX INT for an unsigned int
Formula test: 2147483647
// Binary: all 1s, which is what I expected
Formula Test with Double Cast: -1
Run Code Online (Sandbox Code Playgroud)
最下面的两行是我想要了解的.双重演员给了我预期的"-1"; 但直接转换为MAX_INT提供了一个32位有符号整数.来自C++背景,我会理解它是否给了我一个"奇数"而不是预期的-1(又名"天真的演员"),但这让我感到困惑.
那么,对于那个问题:这是Java中的"预期"行为(例如,任何double直接转换为an的行为int都将被"封顶" MAX_INT)?对任何意外类型进行强制转换吗?我希望它是相似short和byte,例如; 但是当把一个超大双倍的东西放到浮动状态时,"预期的行为"是什么?
谢谢!
esa*_*saj 11
这是预期的行为.请记住,Java中没有原始的unsigned long或int类型,并且用于Narrowing原语转换的Java语言规范(Java 7)(5.1.3)声明抛出"太小或太大"的浮点值(是双倍的)或浮点数到整数类型的int或long将使用有符号整数类型的最小值或最大值(强调我的):
将浮点数转换为整数类型T需要两个步骤:
在第一步中,浮点数转换为long(如果T为long)或转换为int(如果T为byte,short,char或int),如下所示:
- 如果浮点数为NaN(§4.2.3),则转换的第一步结果为int或long 0.
否则,如果浮点数不是无穷大,则浮点值将四舍五入为整数值V,使用IEEE 754舍入为零的模式(第4.2.3节)向零舍入.然后有两种情况:
- 一个.如果T很长,并且该整数值可以表示为long,则第一步的结果是长值V.
- 湾 否则,如果此整数值可以表示为int,则第一步的结果是int值V.
否则,以下两种情况之一必须为真:
- 一个.该值必须太小(大幅度或负无穷大的负值),第一步的结果是int或long类型的最小可表示值.
- 湾 该值必须太大(大幅度或正无穷大的正值),第一步的结果是int或long类型的最大可表示值.*
在第二步中:*如果T为int或long,则转换结果是第一步的结果.*如果T是byte,char或short,则转换结果是第一步结果转换为类型T(第5.1.3节)的结果.
例5.1.3-1.缩小原始转换
Run Code Online (Sandbox Code Playgroud)class Test { public static void main(String[] args) { float fmin = Float.NEGATIVE_INFINITY; float fmax = Float.POSITIVE_INFINITY; System.out.println("long: " + (long)fmin + ".." + (long)fmax); System.out.println("int: " + (int)fmin + ".." + (int)fmax); System.out.println("short: " + (short)fmin + ".." + (short)fmax); System.out.println("char: " + (int)(char)fmin + ".." + (int)(char)fmax); System.out.println("byte: " + (byte)fmin + ".." + (byte)fmax); } }该程序产生输出:
Run Code Online (Sandbox Code Playgroud)long: -9223372036854775808..9223372036854775807 int: -2147483648..2147483647 short: 0..-1 char: 0..65535 byte: 0..-1char,int和long的结果并不令人惊讶,产生了该类型的最小和最大可表示值.
字节和短的结果会丢失有关数值的符号和大小的信息,也会丢失精度.通过检查最小和最大int的低位比特可以理解结果.最小int是十六进制,0x80000000,最大int是0x7fffffff.这解释了短结果,即这些值的低16位,即0x0000和0xffff; 它解释了char结果,它们也是这些值的低16位,即'\ u0000'和'\ uffff'; 它解释了字节结果,它们是这些值的低8位,即0x00和0xff.
因此,第一种情况int formulaTest = (int) (maxUintFromDoubleAsLong * 1.0);促进maxUintFromDoubleAsLong了双倍乘法,然后将其转换为int.由于该值太大而无法表示为有符号整数,因此该值变为2147483647(Integer.MAX_VALUE)或0x7FFFFFFF.
至于后一种情况:
将有符号整数缩小到整数类型T只会丢弃除n个最低位之外的所有位,其中n是用于表示类型T的位数.除了可能丢失有关数值大小的信息之外,这可能导致结果值的符号与输入值的符号不同.
因此,int testFormulaeWithDoubleCast = (int)((long) (maxUintFromDoubleAsLong * 1.0));首先将maxUintFromDoubleAsLong提升为double,返回long(仍然适合)然后再提升为int.在最后一次转换中,多余的位被简单地删除,留下0xFFFFFFFF,当被解释为有符号整数时为-1.
| 归档时间: |
|
| 查看次数: |
2731 次 |
| 最近记录: |