为什么Java和C#都有位移位操作符?

为什么Java和C#都有位移位操作符?,c#,java,low-level,premature-optimization,bit-shift,C#,Java,Low Level,Premature Optimization,Bit Shift,整数乘法(暂时忘记除法)之间的差异是否仍然有利于移位?如果是,差异有多大 这似乎只是一个低级的优化,即使您想要它,(C#/Java)转字节码编译器或jit在大多数情况下不应该捕获它吗 注意:我测试了C#的编译输出(使用gmcs Mono C#编译器版本2.6.7.0),乘法示例即使乘以2的倍数也没有使用shift进行乘法 C# cil 附言。 我忘了在字节上使用它可能有点用处,但在数字上使用它时仍然有一些困难。第一个原因: 有时—大多数情况下—您希望将整数视为数字。有时,虽然整数是表示一组位

整数乘法(暂时忘记除法)之间的差异是否仍然有利于移位?如果是,差异有多大

这似乎只是一个低级的优化,即使您想要它,(C#/Java)转字节码编译器或jit在大多数情况下不应该捕获它吗

注意:我测试了C#的编译输出(使用gmcs Mono C#编译器版本2.6.7.0),乘法示例即使乘以2的倍数也没有使用shift进行乘法

C#

cil

附言。 我忘了在字节上使用它可能有点用处,但在数字上使用它时仍然有一些困难。

第一个原因:

有时—大多数情况下—您希望将整数视为数字。有时,虽然整数是表示一组位的一种方便方式

乘法是对数字的运算

移位是对一组位的操作

乘法的结果和移位的结果之间碰巧存在某种关系,这一点并不特别相关。这些操作在逻辑上是不同的

第二个原因:


C#和Java都是为C开发人员所熟悉而设计的,尽管只是表面上的。因此,C和Java中都包含了C语言中常见的习惯用法。

如果我想将一个数字乘以4,我会编写
*4
。如果我的意图是将某些位左移2位,我会写
你说得对,如果移位运算符仅用作乘法的替代方法,它应该留给编译器

我想您忽略了以下应用程序:

  • 加密/解密
  • CRC计算
  • 位图操作(图形、数据库锁)
  • 压缩/解压缩
  • 为硬件寄存器设置数据
  • 更改编码

更多的人需要在没有本机代码的情况下进行高效的实现。

因为语言设计者认为拥有它们会很好


它们是否等同于其他操作,编译器是否足够聪明以高效地实现操作,这并不重要。如果这就是我们要去的地方,那么您只需要一个宏汇编程序和一个非常好的链接时间优化器,也许在一个带有垃圾收集器的VM上。这些不是语言设计人员通常追求的目标。

您要问的基本上不是为什么C#/Java中会有位移位运算符,而是为什么
javac
编译器不会使用2到位移位的幂来优化乘法和除法

对此的下意识反应是乘法和除法与位移位具有不同的语义,因此它不能100%映射以替换运算


此外,您还忘记了在JIT(热点)中发生的额外编译步骤,在那里会发生各种额外的优化。坦率地说,不需要优化这个特定步骤,而C语言是编译器生成代码的语言。

例如,您的程序可能会使用位掩码之类的东西。在这种情况下,位移位操作是必要的。或者,如果您只是在解决一些需要以指定方式对状态进行编码的奇怪任务


看这个-大多数样本来自数学问题。如果您只是制作一个站点或GUI应用程序,您可能不需要进行移位,但有时确实需要……

这样您就可以左右移位。您希望这些位及其移位操作代表什么完全取决于您。

除了这里的其他原因外,还有很多情况下您可能需要移位(或其他位操作)通过网络与第三方库或远程应用程序接口。

乘法不是位移位运算符的唯一用法。有时位移位运算符比乘法等式更清晰。您可以看到IL,你真的需要在JIT编译完成后查看机器代码,才能判断框架是否正确地优化了这些代码。克里斯蒂安:你是说除法还是说别的?C#和Java(尤其是后者)抛出了很多东西,从C和C++。更重要的是,我很好奇为什么你想代表2字节作为int,如果它不是要一个数字。@罗马是否某事是一个性能瓶颈不能辩论的上下文。如果您在两个字节上有多个操作,例如1000个操作和数千个并发用户,那么这将导致difference@Roman:外部设备的信号:声卡、PLC、,etc@Roman:由于CIDR,IP地址作为位序列而不是数字值是有意义的<代码>(IP地址)和(网络掩码)
处理32位整数的速度大约是在字节数组中循环速度的十倍,使用32位整数比使用展开循环快四倍。我同意位移位使代码更容易读/写,但您可以不用它们,只需使用*2^n或/2^n而不用n。因此,他们不是必需的,但很好have@RuneFS,-1>>1与-1/2不同,无论符号是否扩展。只使用数学运算符重写移位运算实际上相当麻烦。@Jon你错过了一点,那就是它们不是必需的,但可以重写(符号在谈论位模式时毫无意义,因为它们推断出模式的特定解释,而模式本身并不是模式的一部分。例如,在给定的上下文中有多个位模式表示-1,它们在不同的上下文中都表示一个正整数,并且文件的一部分在另一个上下文中被加密她context@RuneFS,你没有理解我的观点,它们不能被简单地重写。我们可以重写每一条只有减法和分支的指令,如果是负数的指令,但是我们有很好的理由不重写。最后,当你说话的时候,你说明了我的观点