按位移位操作选择



大家好,我正在学习Java编程,我想知道为什么选择这个 符号位传播是">>"而不是">>>"? 我认为<<和>>应该具有相同的实现。 对不起,如果这听起来像是一个愚蠢的问题:)

提前感谢!

它以这种方式工作的原因是,C和C++早在Java之前就使用<<左移,>>用于右移。 这些语言既有有符号类型,也有无符号类型,对于有符号类型,符号位在右移情况下传播。

Java没有无符号类型,所以他们保留了C和C++的行为,以免造成混乱并招致全世界开发人员的无休止的愤怒。 然后,他们包括>>>以提供将位值视为无符号的右移。

这个问题实际上是关于阅读詹姆斯·高斯林的思想:-)。 但我的猜测是,<<>>在数学上都是有意义的:<<导致一个数字乘以2(除非溢出),>>导致一个数字被除以2 - 当你有符号传播时,无论数字是正数还是负数,这都有效。 也许语言设计者认为这将是右移位的更常见的用法,而不是传播 0 的运算符,当整数被视为位字符串而不是实际数字时,这更有用。 这两种方式都没有"对"或"错"之分,如果高斯林那天早上早餐吃了不同的东西,他可能会以你的方式看待事情......

让我们从你没有问的问题开始:-)

问:为什么没有<<<

A1:因为<<>>>>>执行适当的反向操作。

  • >> N相当于有符号整数除以 2N
  • >>> N相当于无符号整数除以 2N
  • << N相当于有符号整数和无符号整数的乘以 2N

A2:因为符号位在左手端,所以当你向左移动时"延伸"它是无意义的。 (旋转是有意义的,但Java没有任何"旋转"运算符。 原因:C 先例,某些指令集缺乏硬件支持,Java 代码中很少需要旋转。

问:为什么只有>>>>>中的一个签署延期

答:因为如果他们都这样做(或都没有),那么你就不需要两个操作员了。


现在回答你的问题(我认为):

问:为什么他们选择>>进行标志扩展而不是>>>

答:这确实是无法回答的。 据我们所知,没有现存的公开记录原始Oak/Java语言设计决策。 充其量,我们必须依靠詹姆斯·高斯林的记忆......以及他愿意回答问题。 AFAIK,这个问题还没有被问过。

但我的猜想是,由于Java整数类型(大部分)是有符号的,因此人们认为>>运算符会更频繁地使用。 事后看来,我认为高斯林等人说得对。

但这不是关于复制 C 或 C++。 在这些语言中,只有一个右移运算符(>>),它对有符号整数的行为是实现定义的!!。 Java 中的>>>运算符旨在解决这个问题;即消除C/C++>>的可移植性问题。

(参考:C11语言规范草案第6.5.7节)

接下来您的评论:

我认为<<>>应该具有相同的实现。 通过相同的实现,我的意思是相同的过程,但方向相反。

上面回答了这个问题。 从有用的功能的角度来看,>><<确实对有符号号码执行相同的过程,但方向不同;即除法与乘法。 对于无符号数字<<<以相同的方式对应于>>

为什么会有差异? 它基本上取决于 2 的补码和无符号二进制表示的数学。

请注意,您不能执行>>>>>的数学逆运算。 直观地说,这些操作员会丢弃右端的钻头。 一旦扔掉,这些位就无法恢复。

问:那么他们为什么不让<<(或假设的<<<)"伸出"右手位呢?

答:因为:

  • 这是没有用的。 (我想不出任何主流用例来扩展数字的右手位。
  • 通常没有硬件支持(...因为它没有用!

最新更新