5

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

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

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

C# http://csharp.pastebin.com/hcrRnPrb

cil http://csharp.pastebin.com/0js9F2c1

PS我忘记了在字节上使用它可能会有些用处,但在将它用于数字时仍然遇到一些麻烦。

4

8 回答 8

22

第一个原因:

有时——大多数时候——你想把一个整数当作一个数字来对待。有时,尽管整数是表示一组位的便捷方式。

乘法是对数字的运算。

移位是对一组位的操作。

乘法结果和移位结果之间恰好存在关系并不是特别相关。操作在逻辑上是不同的。

第二个原因:

C# 和 Java 都是为了让 C 开发人员熟悉而设计的,尽管只是肤浅的。因此,来自 C 的常见习语被包含在 C# 和 Java 中。

于 2010-10-01T05:02:35.377 回答
12

如果我想将一个数字乘以 4,我会写* 4. 如果我的意图是将某些位左移 2 位,我会写<< 2.

重新提出问题:

为什么 Java 和 C# 有位移运算符?

我在二进制数据上做了很多工作,我没有考虑整数等- 只是二进制 - 在那个领域,不断使用移位运算符是完全合乎逻辑的。

当然,我可以输入* 2等,但我真正想做的是移位。

这在字节很重要的一系列领域(例如图形编程、序列化等)中很常见。

此外,移位操作有一些微妙之处,您希望它表现得像一个整数,特别是在处理边缘时...... -shift 位映射中(-ve vs +ve 等)很好理解但很关键。同样,整数乘法的checked/unckecked行为有时也很重要。

于 2010-10-01T05:24:08.623 回答
8

你是对的,如果移位运算符仅用作乘法的替代,它应该留给编译器。

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

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

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

于 2010-10-01T05:47:37.880 回答
1

您要问的本质上不是为什么 C#/Java 中有移位运算符,而是为什么javac编译器不将乘法和除法以 2 的幂次优化为移位。

对此的下意识反应是乘法和除法的语义与位移不同,因此它不会 100% 映射来替换操作。

此外,您忘记了在 JIT (HotSpot) 中发生的额外编译步骤,在该步骤中会发生各种额外的优化。坦率地说,没有必要优化这个特定的步骤,与 C 中的代码在编译器生成它时相反。

于 2010-10-01T05:58:24.440 回答
0

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

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

于 2010-10-01T05:56:35.940 回答
0

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

观看本教程- 大多数示例来自数学问题。如果您只是制作一个站点或 GUI 应用程序,您可能不需要转换,但有时您确实需要...

于 2010-10-01T06:04:14.320 回答
0

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

于 2010-10-01T06:12:11.650 回答
0

除了这里的其他原因之外,在很多情况下,您可能需要转换(或其他位操作)以通过网络与 3rd 方库或远程应用程序接口。

于 2010-10-01T06:14:08.090 回答