为啥“-3 >> 1”不会产生与“-3 / 2”相同的结果? [复制]
Posted
技术标签:
【中文标题】为啥“-3 >> 1”不会产生与“-3 / 2”相同的结果? [复制]【英文标题】:Why "-3 >> 1" does not produce the same result as "-3 / 2"? [duplicate]为什么“-3 >> 1”不会产生与“-3 / 2”相同的结果? [复制] 【发布时间】:2018-02-16 21:24:32 【问题描述】:考虑以下 c++ 代码:
int main()
int a = -3 >> 1;
int b = -3 / 2;
cout << "a = " << a << ", b = " << b << endl;
return 0;
执行时,此代码给出以下结果:
a = -2, b = -1
我有点困惑,因为我认为这两个操作在编译的 exe 中产生了相同的代码,即:
shr ax, 1
但似乎情况并非如此(我用 2 个不同的编译器进行了测试)。有人可以向我解释为什么这些操作不会产生相同的结果?
---- 编辑于 17.02.2018 ----
好吧,我知道这是一个新手问题,即使我不是真正的 C++ 初学者
事实上,当我对一个值应用右移(即 shr 或 >> 运算符)时,我完全理解二进制会发生什么。 这不是我的问题。
相反,我的问题是关于对值应用二进制移位或对值进行除法之间的区别。 我预计结果是一样的,因为直到现在我都假设编译器在编译期间用适当的 shr/shl 指令替换除以 2 或乘以 2,作为优化.假设两条指令生成的二进制文件应该相同,那么结果也应该相同。
但显然不是这样。出于这个原因,我很高兴知道编译器编译这两条指令(分析助记符并不是我的强项)的底层发生了什么,它们有什么区别,最后,这个应该让我理解为什么结果在数学方面有所不同。
作为一个具体案例,我在试图简化的图形应用程序的源代码中遇到了这个问题。为了便于人类阅读代码,我将一些代码如“(widthB - widthA) >> 1”替换为“(widthB - widthA) / 2”。但是这样做引入了一个错误:几个图形项目不再像预期的那样居中。从中我注意到,如果除法的值为负,则用除法替换移位会产生不同的结果,这就是上述问题的原因。
我希望这能解决问题。
【问题讨论】:
首先,打消你脑中C++是根据CPU操作定义的观念 我不清楚哪一部分让你感到困惑。你不明白为什么-3 >> 1
产生-2
,或者为什么-3 / 2
产生-1
?
关于您的编辑,我认为您错过了一个非常基本的方面:并不是它们产生不同的结果,因为它们的编译方式不同。那是倒退。它们的编译方式不同,因为它们应该产生不同的结果(部分是因为标准是这样说的,部分是因为它依赖于实现并且实现是这样说的)。 -3 >> 1
应该产生-2
,-3 / 2
应该产生-1
,如果它们应该产生不同的结果,显然需要不同的指令。
thx hvd,您的评论回答了我的问题。这正是我想知道的。
【参考方案1】:
二进制补码系统中的-3
11111111111111111111111111111101 :BIN
当右移时
11111111111111111111111111111110 :BIN
这意味着十进制的 -2。
但是,当您将两个数字相除时,例如 -3 / 2
,答案是 -1.5,而将其转换为整数时,答案是 -1。
【讨论】:
补体系统怎么样?由于 C++ 两者都支持。为了完整起见。 @Eljay 不同 ~3 -> 11111111111111111111111111111100 和右移 1111111111111111111111111111110 -> ~1 不同 -3 和 ~3 -3 是补码 ~3 是补码【参考方案2】:这与内部表示有符号和无符号数字的方式有关,如果您试一下此代码,您会发现它的行为符合预期。
#include <iostream>
using namespace std;
int main()
unsigned int a = 3 >> 1;
unsigned int b = 3 / 2;
cout << "a = " << a << ", b = " << b << endl;
return 0;
我建议查找“双恭”
【讨论】:
C++ 不需要恭维。 @user4581301 但我不知道有任何现代平台不使用 2 的恭维。 @SergeyA 那只是因为 Jack Tripper 用他古怪的滑稽动作搞砸了 Three's Compliment。以上是关于为啥“-3 >> 1”不会产生与“-3 / 2”相同的结果? [复制]的主要内容,如果未能解决你的问题,请参考以下文章