为啥“-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 &gt;&gt; 1 产生-2,或者为什么-3 / 2 产生-1 关于您的编辑,我认为您错过了一个非常基本的方面:并不是它们产生不同的结果,因为它们的编译方式不同。那是倒退。它们的编译方式不同,因为它们应该产生不同的结果(部分是因为标准是这样说的,部分是因为它依赖于实现并且实现是这样说的)。 -3 &gt;&gt; 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”相同的结果? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 ( x & 3 ) 与 ( x mod 4 ) 相同?

为啥python的列表切片不会产生索引越界错误? [复制]

为啥 Pandas 不会产生不明确的时间错误?

为啥连续抛出 2 个异常不会产生无法访问的代码警告?

为啥大型静态数组会产生段错误而动态却不会? (C++)

为啥我的法线不会在顶点之间插值,从而产生平坦的阴影效果?