C# 中的“>>”运算符有啥作用?
Posted
技术标签:
【中文标题】C# 中的“>>”运算符有啥作用?【英文标题】:What does the ">>" operator in C# do?C# 中的“>>”运算符有什么作用? 【发布时间】:2011-03-29 23:16:41 【问题描述】:我在一段代码中遇到了这个语句:
Int32 medianIndex = colorList.Count >> 1;
colorList
是类System.Drawing.Color
的列表。
现在该语句应该检索列表的中位数索引 .. 就像它的半点一样 .. 但我无法理解 >>
符号是如何工作的,以及“1”应该如何给出中位数指数..我将不胜感激:S
【问题讨论】:
【参考方案1】:>>
运算符执行bit shift。
表达式>> 1
几乎* 与/ 2
相同,因此程序员正在计算索引colorList.Count / 2
,即**median。要了解为什么会出现这种情况,您需要查看所涉及数字的二进制表示。例如,如果您的列表中有 25 个元素:
n : 0 0 0 1 1 0 0 1 = 25
\ \ \ \ \ \ \
n >> 1: 0 0 0 0 1 1 0 0 = 12
一般来说,当你真的想要执行除法时使用按位运算符是一种不好的做法。这可能是一个过早的优化,因为程序员认为执行按位运算而不是除法会更快。写一个除法会更清楚,如果两种方法的性能相当,我不会感到惊讶。
*表达式x >> 1
对所有正整数和所有负偶数给出与x / 2
相同的结果。但是,对于负奇数,它给出了不同的结果。例如-101 >> 1 == -51
而-101 / 2 == -50
。
**实际上,只有当列表具有奇数个元素时,才以这种方式定义中位数。对于偶数个元素,这种方法严格来说不会给出中位数。
【讨论】:
非常感谢您的解释..我熟悉移位方法及其含义,但我不明白这是这里使用的方式..我还有另一个问题..这是对 2 进行除法的时间复杂度低于普通的“/”除法? @Majd:这取决于您运行代码的平台。请记住,C# 被编译为 CIL,而 CIL 又被翻译(“jitted”)为不同平台的本地机器代码。有些抖动很可能会自动将x/2
转换为右移指令。
在第一个脚注中,将x >> 1
与x /= 2
进行比较有点令人困惑,我认为=
符号是一个错字。当然x >> 1
与x / 2
相当,x >>= 1
与x /= 2
相当。【参考方案2】:
这是一个按位运算符,我刚刚从http://en.wikibooks.org/wiki/C_Sharp_Programming/Operators 获取的定义:
二元运算符>>计算其操作数并返回结果第一个参数右移了第二个参数指定的位数。它丢弃超出其第一个参数大小的低位,并将新的高位设置为第一个参数的符号位,如果第一个参数是无符号的,则设置为零。
它基本上是除以 2...
【讨论】:
+1 用于链接到文档。我发现如果有趣的话,OP 甚至会费心在这里发帖,而不是仅仅前往语言定义。问这样的问题会让我和我的员工谈论他们的态度(不是:我不明白什么是 bigshift”,而是“嘿,我懒得查找我审查的代码的语言规范”)。【参考方案3】:>>
是按位右移运算符,将colorList.Count
右移 1 或多或少等同于 colorList.Count / 2
。
a >> b
的右移可以定义为a / 2 ^ b
。
至于为什么要使用右移而不是除以 2,我不知道。
【讨论】:
不要使用它而不是除以 2。JIT 优化了这种东西。【参考方案4】:C 程序员(我已经是其中一员 20 多年了)通常使用按位移位来乘以或除以 2 的幂。原因是在较旧的架构中(想想 2 MHz 处理器、32K 内存和没有磁盘)转移速度明显更快,并且通常编译为单个机器指令。尽管我现在主要编写 C#,但出于习惯,我仍然有时会使用这个技巧。大多数 C# 程序员从未见过的另一个常见 C 约定是在条件中嵌入赋值。例如:
if ( (a = getmeanumber()) == 0 )
/* do something */ ;
无论如何,至于最初的问题和使用它的原因,它们基本上不再存在,除非在嵌入式编程的有限领域中每个字节和时钟周期都可能很重要。
【讨论】:
【参考方案5】:这不是很可读的代码,基本上它只是将数字除以2。
>>
是右移运算符,将所有位右移一位。
0110 (6) 变为 0011 (3)
【讨论】:
以上是关于C# 中的“>>”运算符有啥作用?的主要内容,如果未能解决你的问题,请参考以下文章