【问题标题】:Using tilde to get MAX value for int使用波浪号获取 int 的 MAX 值
【发布时间】:2011-03-25 21:39:30
【问题描述】:

我尝试使用波浪号获取 int 的 MAX 值。但输出不是我所期望的。 当我运行这个时:

#include <stdio.h>
#include <limits.h>
int main(){
    int a=0;
    a=~a;
    printf("\nMax value: %d",-a);
    printf("\nMax value: %d",INT_MAX);
    return 0;
}

我得到输出:

最大值:1

最大值:2147483647

我想,(例如)如果我在 RAM 中有 0000(我知道第一位显示的是数字 pozitiv 或负数)。之后 ~ 0000 => 1111 和之后 -(1111) => 0111 ,我会得到 MAX 值。

【问题讨论】:

  • "using tilde" - 如果你想获得 int 的最大值,总是使用INT_MAX。由于您标记了这个问题 C++,您还可以在 #include &lt;limits&gt; 之后使用 numeric_limits&lt;int&gt;::max()(如果您喜欢过于冗长,或者如果您需要切换类型。)

标签: c++ c memory


【解决方案1】:

您有一个 32 位二进制补码系统。所以 - a = 0 很简单。 ~a0xffffffff。在 32 位二进制补码表示中,0xffffffff-1。基本代数解释说-(-1)1,所以这就是您的第一个打印输出的来源。 INT_MAX0x7fffffff

您的逻辑错误在于以下语句:“-(1111) => 0111”,不正确。二进制补码的算术求反运算等效于~x+1 - 例如:

~x + 1 = ~(0xffffffff) + 1
       = 0x00000000 + 1
       = 0x00000001

【讨论】:

  • @DarkDust - 没有。 abs(~0)abs(0xffffffff)abs(-1)1,和OP的问题一样。
  • @Darkdust - 不,没有一个 int 是 abs(~0)。应该是 INT_MAX + 1。
  • @Bo,又错了。 abs(~0)1,至少给定abs() 的合理实现。
  • 总是一个有趣的面试问题。至少在 Java 中,Math.abs() 被定义为在传递 Integer.MIN_VALUE 时返回 -'ve 答案 - 因为它不能返回 +'ve 答案。
  • @dty,这是真的 - abs() 的标准 C 实现的文档说“最大负整数的绝对值仍然是负数。”在BUGS 部分。鉴于 OP 的程序,printf("%d", abs(a)) 也将最终打印 1
【解决方案2】:

您是否有不能使用std::numeric_limits&lt;int&gt;::max() 的原因?犯简单的错误要容易得多,而且不可能。

在你的情况下,假设 32 位 int:

int a = 0;   // a = 0
a = ~a;      // a = 0xffffffff = -1 in any twos-comp system
a = -a;      // a = 1

因此,数学是一种不正确的计算机方式。我看不到计算最大值的公式化方法:只需使用 numeric_limits(或 INT_MAX,如果您在纯 C 代码库中)。

【讨论】:

    【解决方案3】:

    您使用“~”获取最大值的技巧适用于 unsigned 整数。正如其他人指出的那样,它不适用于 signed 整数。

    您的帖子显示int,相当于signed int。尝试将类型更改为unsigned int,看看会发生什么。

    【讨论】:

      【解决方案4】:

      没有公式可以计算 C 中带符号整数类型的最大值。您只需使用来自 limits.hstdint.hINT_MAX 等宏。 p>

      【讨论】:

        【解决方案5】:

        二进制1...1111 将始终代表-1。简单的数学说-1 * -1 = 1! 永远记住只有一个零:0...0000。如果您现在交换 MSB 并且您是对的,那么您将拥有 10...0000 这将是 -0 这不可能是真的(如数学中的 0 = -0,但您的二进制数将是不同)。

        获取数字的负值不仅仅是交换 MSB。

        【讨论】:

        • 错了。二进制 1...1 表示 -1 仅适用于 signed 整数类型。
        • 嗯,对,但在上面的例子中,他实际上使用的是int-而不是unsigned int
        • 在解释和说明计算机如何工作时,需要极其精确地使用语言。这不是允许理论和概念不总是有效的软科学。
        【解决方案6】:

        它不像指示符号的最高位那么简单。如果是这样,您可以同时拥有 +0 和 -0。您应该阅读二进制补码。

        正确答案是

        max = (~0) >> 1;  
        

        我不是 C/C++ 专家,因此您可能需要&gt;&gt;&gt;。您需要不进行符号扩展的移位运算符。

        【讨论】:

        • 问题在于,对于包含负值的 signed 类型,&gt;&gt; 运算符是实现定义的(C++ §5.8 ¶3),在 C 和 C++ 中,您无法精确控制&gt;&gt; 运算符处理符号位。但是,您可以通过 unsigned 类型在该类型上使用 &gt;&gt;
        • 愚蠢的语言! ;-) 你的意思是你不能要求它在没有符号扩展的情况下进行轮班?
        • @dty:是否使用符号扩展是实现定义的。但是您始终可以使用 unsigned 类型在没有符号扩展的情况下获得 shift。
        • 类似(记住,我不是 C/C++ 人):((unsigned int)~0) &gt;&gt; 1 ?
        • @dty,这会很好,是的。对于符号幅度或 2 的补码实现,即!
        【解决方案7】:

        在 2 的补码表示法中 111111... 是 -1;现在,一元减号运算符不只是更改符号位(否则它会在每个正常上下文中提供奇怪的结果),而是正确计算数字的相反数,即 +1。

        如果您想更改 MSB,您可以使用位运算符将其简单地设置为零。但是请注意,这种查找 int 类型最大值的方法是不可移植的,因为您正在对标准不要求的数字表示方式做出假设。

        【讨论】:

          猜你喜欢
          • 2019-07-07
          • 2019-04-09
          • 2012-10-10
          • 1970-01-01
          • 1970-01-01
          • 2017-03-29
          • 2013-07-25
          • 2016-12-06
          • 2011-06-06
          相关资源
          最近更新 更多