“possible loss of precision”是Java出毛病还是我漏掉了什么?

4

我在本应该没有问题的情况下,遇到了“精度丢失”的错误。

这是一个实例变量:

byte move=0;

这是发生在该类方法中的事情:
this.move=(this.move<<4)|(byte)(Guy.moven.indexOf("left")&0xF);

移动是一个字节,移动仍然是一个字节,其余部分被强制转换为字节。

我收到了这个错误:

[javac] /Users/looris/Sviluppo/dumdedum/client/src/net/looris/android/toutry/Guy.java:245: possible loss of precision
[javac] found   : int
[javac] required: byte
[javac]             this.move=(this.move<<4)|(byte)(Guy.moven.indexOf("left")&0xF);
[javac]                                         ^

我尝试了很多种变化,但是仍然得到相同的错误。

现在我毫无头绪。


1
如果移动的位数是128怎么办?当您将其向左移动4位时,这将导致精度损失。 "byte << N"被定义为返回另一个字节还是整数? - Lasse V. Karlsen
3个回答

8

这是因为this.move<<4返回一个int类型。

当Java遇到位移操作符时,它会对每个操作数应用一元提升;在这种情况下,两个操作数都被提升为int类型,结果也是如此。 其他Java运算符的行为类似;请参阅相关且有指导意义的讨论“可能丢失精度的不同行为”。


这个链接对我非常有用,但是里面没有关于位移操作的例子。那里的解释是关于复合赋值语句的。 - CEGRD

8

实际上所有的逻辑运算符 (& | ^) 都会返回一个整数,不管它们的操作数是什么。你需要将 x|y 的最终结果也强制转换为整数。


哦!谢谢!(也感谢leonbloy和ZZ) - o0'.

5
按位或运算符需要进行二进制数字提升。以下是JLS中的定义:
5.6.2 二进制数字提升
当运算符将二进制数字提升应用于一对操作数时,每个操作数都必须表示为一个数字类型的值,并按照以下规则应用,使用扩展转换(§5.1.2)根据需要转换操作数:
如果任一操作数是double,则将另一个操作数转换为double。
否则,如果任一操作数是float,则将另一个操作数转换为float。
否则,如果任一操作数是long,则将另一个操作数转换为long。
否则,两个操作数都将转换为int类型。
如您所见,没有byte类型,因此所有字节默认情况下都会被升级为int。您必须将其重新转换为byte以消除警告。
this.move=(byte)((this.move<<4)|(Guy.moven.indexOf("left")&0xF));

实际上这里发生了一对一元数值提升,而不是二元的,请参见http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#5121。 - leonbloy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接