【问题标题】:Converting from int to binary string to int using 2's complement使用 2 的补码从 int 转换为二进制字符串到 int
【发布时间】:2012-11-22 16:54:48
【问题描述】:

有一个二进制字符串10001110,我知道它使用的是 2 的补码。我知道它将是 8 位。

它以unsigned int 的形式提供给我,等于 142。

然后我需要将其转换回10001110

然后将所有位反转并加一,结果等于01110010

然后将其转换为等于 -114 的 signed int

我该怎么做?我对 C 语言比较陌生,并且花了很长时间试图弄明白!

基本上我想编写一个函数,它接受unsigned int 142 并返回signed int -114

【问题讨论】:

  • 它总是有 8 位?还是什么?
  • 是的,在这种情况下,我知道它是 8 位。不过,我希望能够将其作为参数传递给函数。
  • 01110010 不只是 114(不是 -114)吗?
  • 1) 转换为unsigned char,2) 使用按位“非”,3) 转换为int
  • @KerrekSB 你忘了“加一个” ;-)

标签: c binary int bit-manipulation twos-complement


【解决方案1】:

想想你可以用位运算符做什么。您可以像这样测试一个位是 1 还是 0:

int bit = value & 1;

您也可以像这样移动 int 中的位:

val = val >> 1;

要测试 int 中的第 i 位,您可以这样做:

int bit = (value >> i) & 1;

因此,使用此信息,您可以将给定的整数转换为二进制并将其存储在一个 char 数组中(如果您向上计数,它将以相反的顺序排列!)然后根据您的喜好操作 char。希望这是一个足够大的提示,可以让您站起来并开始。

【讨论】:

  • 这听起来像很多工作,当操作员~ 可以一次反转所有位时。
  • 虽然 ~ 将反转所有位,但实际上仅使用前 8 位,因此只有这 8 位应反转。所有其他位都已设置为 0。
【解决方案2】:

您无需更改位模式。您只需要进行符号扩展以匹配已签名 int 结果的位长度。最简单的方法是检查输入的符号位,然后如果设置了位长度,则将 -1 向左筛选。

int toSignedInt(unsigned int value, int bitLength)
{
    int signedValue = value;
    if (value >> (bitLength - 1))
        signedValue |= -1 << bitLength;
    return signedValue;
}

说明

在 8 位二进制补码中,无符号 142 和有符号 -114 的位模式相同。所以如果你的整数类型是 8 位,你只需要转换类型。但是,如果您有 32 位整数,但您想将它们视为 8 位二进制补码,那么您需要将左侧 24 位设置为 1,如果符号位是1.

【讨论】:

  • 128 &amp; -1 == 128,如果我们假设二进制补码。如果我们不这样做,那么 $DEITY 知道你会得到什么。
  • 我一直认为x &amp;= -1根本不会改变x。也许你的意思是'x ^= -1`?
  • 多哈。我的错误应该是value | (-1 &lt;&lt; bitLength)
  • 感谢您的解释。我现在开始明白了!这是否依赖于使用 2 的补码的计算机(与符号和大小等其他东西相反)? intsigned int 一样吗?
  • 是的,这依赖于使用二进制补码的编译器。是的,int 通常与signed int 相同。
【解决方案3】:

你不能从给定的任何值中减去 256 吗?

【讨论】:

  • int func(unsigned int value) { return (unsigned char)(-value); } 也可以完成这项工作。
【解决方案4】:

老兄 - 你为什么要结束你原来的问题????

我的回答和第一个一样:

  • 整数就是整数。无论是“签名”还是“未签名”;无论是“一个补码”还是“二进制补码” - 位总是相同的。

  • 如果您想将有符号值“转换”为无符号值,C 转换通常是最好、最简单、最有效和最清晰的方法(下面的代码示例)。

  • 绝大多数 CPU 架构都是二进制补码

  • 如果出于某种原因,您想检查您的 CPU 架构是否是反码,那么只需测试 -0 == +0。二进制补码没有“负零”(只是零)。补码可以。

PS:

问:本质上我想写一个函数来接受 unsigned int 142 并返回带符号的 int -114

答:

int silly_convert (int i)
{
  return (signed char)i;
}

这与我在回复您原来的帖子时所建议的完全一样。

【讨论】:

  • 我关闭了这个问题,因为我没有很好地解释它。
【解决方案5】:

这是我最终想出的解决方案。

#include <stdio.h>
#include <stdlib.h>

int getBit(int no, int bit) // get bit at certain position
{
    bit--;
    return (no & (1 << bit)) >> bit;
}

void complementNBits(int *no, int count) // invert certain number of bits
{
    int i;
    for(i=0; i<count; i++)
    {
        *no ^= 1 << i;
    };
}

int main() 
{
    unsigned int unsignedNo=142;

    int negative = 0;   
    signed int signedNo=0;

    // check if MSB is set to determine if negative

    if (getBit(unsignedNo, 8)) // if MSB is set
    {
        negative = 1;
        // invert these 8 bits and add 1. the rest of the MSBs will already be 0
        complementNBits(&unsignedNo, 8);
        unsignedNo++;
    }

    signedNo = unsignedNo;
    if (negative)
    {
        signedNo = signedNo * -1;
    }

    printf("THE SIGNED INTEGER: %i\n", signedNo);

}

感谢大家的帮助!

【讨论】:

  • 呃……为什么?!?请再看看我的回复。为什么你不能只是“铸造”价值? “整数是整数...... 总是相同”的哪一部分你不明白吗???
  • 它不起作用,因为 MSB(符号)位会在错误的位置,因为 int 不等于 8 位。
  • 如果我对您的理解正确,我想您会感到困惑。 8 位“-142”与 32 位“-142”具有相同的低 8 位和相同的“1”MSB。或 16 位或 64 位“-142”。唯一的区别是一个比其他的窄,左边的“1”位更少。您确实 NOT 需要进行任何折磨人的位位操作来获得您正在寻找的价值。试试看:)
  • 如果我这样做 printf("%i\n", (signed int) unsignedInt); 它会给我错误的 no :/
猜你喜欢
  • 1970-01-01
  • 2012-02-14
  • 1970-01-01
  • 2013-01-30
  • 2016-07-16
  • 2014-11-28
  • 2021-02-23
  • 1970-01-01
相关资源
最近更新 更多