Java中负字节和短数据类型中的位操作 [英] Bit manipulation in negative byte and short data types in Java
问题描述
我正在尝试实现一个存储32位数字的类,而不使用int
原语类型.为此,我使用两个short
变量msbs
和lsbs
来存储数字的32位,每个变量16位.
变量msbs
将存储数字的前16位,变量lsbs
将存储数字的前16位.
Im trying to implement a class that stores a 32-bit number without using the int
primitive type. For doing so, I'm using two short
variables msbs
and lsbs
to store the 32 bits of the number, 16 bits in each variable.
The variable msbs
will store the first 16 bits of the number and the lsbs
variable the 16 bits left.
当将给定的字节保存到变量时,我应用下一个公式:(字节顺序以Little-Endian表示法给出)
When It comes to save the given bytes to the variables I apply the next formula: (The bytes order are given as Little-Endian notation)
输入-> byte[] n = {0b00110101, -3, 0b1001, 0b0};
到数字0b00000000 00001001 11111101 00110101(654645)
Input -> byte[] n = {0b00110101, -3, 0b1001, 0b0};
to the number 0b00000000 00001001 11111101 00110101 (654645)
msbs = ((n[3] << 8) | n[2]);
lsbs = ((n[1] << 8) | n[0]);
msbs = ((n[3] << 8) | n[2]);
lsbs = ((n[1] << 8) | n[0]);
如下所示
private void saveNumber(byte[] n) {
msbs = (byte)((n[3] << 8) | n[2]);
lsbs = (byte)((n[1] << 8) | n[0]);
System.out.println(Integer.toBinaryString((n[1] << 8) | n[0]));//Prints 11111111111111111111110100110101
System.out.println("msbs -> " + Integer.toBinaryString(msbs));
System.out.println("lsbs -> " + Integer.toBinaryString(lsbs));//Prints 110101
}
行
System.out.println(Integer.toBinaryString((n[1] << 8) | n[0]));//Prints 11111111111111111111110100110101
精确地打印了我需要的内容,尽管在开始时有大量无用的1位(我可以将其强制转换为short
来消除它们)
但是,当我打印lsbs
时,我存储的值完全相同(显然),当它应该为0b1111110100110101
prints exactly what I need, despite the huge amount of useless 1's bits at the beggining (of which I can get rid of just by casting it to short
)
But when I print the lsbs
where I store the exact same value (apparently) it outputs 110101 when It should be 0b1111110100110101
为什么会出现这种现象?我了解这一定与Java在将值11111111111111111111110100110101
存储为16位原始类型时执行的内部"强制转换有关(我个人认为,由于将8位移至剩下一个8位数字,应该给我一个16位数字)
附带说明一下,msbs
变量确实可以实现我想要的功能,因此问题应该与Java表示负数的方式有关
Why does this behavior occur? I understand It must be something with the "internal" casting performed by Java at the time of store the value 11111111111111111111110100110101
into a 16 bits primitive type (Which personally, I think sholdn't be happening because I am shifting 8 bits to the left in an 8-bits number which should give me a 16-bits number)
As a side note, the msbs
variable is doing exactly what I want it to do, so the problem should be related to the way that Java represents the negative numbers
顺便说一句,我知道Java并不是完全有趣的语言.
Btw, I know Java isn't exactly the best language to have fun with bits.
推荐答案
为什么会出现这种现象?
Why does this behavior occur?
在Java中,所有按位运算都是32或64位运算.这与某些其他语言不同,并且可能是意外的.但这就是它.
In Java, all bitwise operations are 32 or 64 bit operations. This is different from some other languages, and can be unexpected. But it is what it is.
我了解这一定与Java进行的内部"转换有关.
I understand It must be something with the "internal" casting performed by Java ....
在您的任何示例中,Java均未进行隐式缩小强制转换 1 .实际上,我认为导致意外行为的原因是代码中的转换范围明显缩小:
Java doesn't do an implicit narrowing casts in any of your examples1. In fact, I think that the cause of the unexpected behaviour is an explicit narrowing cast in your code:
msbs = (byte)((n[3] << 8) | n[2]);
您已明确将32位值从((n[3] << 8) | n[2])
强制转换为byte
.根据您的期望,您应该转换为short
.
You have explicitly cast a 32 bit value from ((n[3] << 8) | n[2])
to a byte
. Based on what you say you expect, you should be casting to short
.
在旁边:当您编写这样的内容时,"我个人认为这不会发生……" 这意味着您正在怀疑Java编译器的正确性.实际上,在99.999%的情况下 2 ,真正的问题是有人不了解编译器应该怎么做;即他们对语言的了解太浅 3 .在大多数情况下,有一种编程语言的规范可以精确地精确地表达特定构造的含义.在Java情况下,它就是Java语言规范.
Aside: When you write things like this "Which personally, I think sholdn't be happening ..." it implies that you are doubting the correctness of the Java compiler. In fact, in 99.999% of cases2, the real problem is someone does not understand what the compiler should do with their; i.e. their knowledge of the language is too shallow3. In most cases, there is a specification of the programming language that says precisely what a particular construct means. In the Java case, it is the Java Language Specification.
1-实际上,我只能想到赋值运算符中原始类型会在内部缩小的地方.
2-我增加了这个数字,但要点是,编译器错误很少是应用程序意外行为的原因.
3-也许这只是程序员错过的一个应用程序错误.疲倦会对大脑造成不良影响...
这篇关于Java中负字节和短数据类型中的位操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!