英文:
When I do bitwise flip operation in C on integer 1, I get -2 and not 4294967294, how can I get 4294967294?
问题
这是一个新手级别的HackerRank问题,要求翻转由32位表示的长整数的位,并返回结果。
例如:
1 被表示为:00000000 00000000 00000000 00000001
~ 运算符翻转位。
所以 ~1 = 11111111 11111111 11111111 11111110
当我在长整数上执行 ~1 时,它返回的是 -2,而不是 4294967294,尽管它们在32位二进制形式中表示相同。
我实现了以下代码:
long flippingBits(long n) {
unsigned long m = n;
unsigned long x = ~n;
return x;
}
我得到了 -2 作为结果。我尝试了只使用 "long",但得到了相同的结果。我还尝试了使用强制类型转换 unsigned long x = (unsigned long)~n;
,但结果仍然相同。
所以后来我只是使用了异或操作,它起作用了:
long flippingBits(long n) {
unsigned long m = n;
unsigned long x = n ^ 4294967295;
return x;
}
为什么在C中 ~ 操作符对于 1 不会表示为 4294967294 而是 -2 呢?如果可能的话,我需要做什么来让 ~ 运算符返回 4294967294 而不是 -2?
英文:
It's one of the newbie HackerRank problems, where it asks to flip bits of a long represented by 32 bits, and return the value.
e.g.:
1 is represented as: 00000000 00000000 00000000 00000001
~ operator flips its bits.
so ~1 = 11111111 11111111 11111111 11111110
When I do ~1 on a long, it returns -2, not 4294967294 despite both are represented equally in 32 bit binary form.
I implemented the code below:
long flippingBits(long n) {
unsigned long m = n;
unsigned long x = ~n;
return x;
}
I got -2 as result. I tried with just "long", but got same result. I tried casting too with unsigned long x = (unsigned long)~n;
but got same results again.
So then I just used XOR operation and it worked:
long flippingBits(long n) {
unsigned long m = n;
unsigned long x = n ^ 4294967295;
return x;
}
Why ~ operation of 1 not represented as 4294967294 but -2 in C? What do I need to do to make ~ operator return 4294967294 and not -2 (if it's possible)?
答案1
得分: 1
在一些平台上,sizeof long == sizeof int
。
标准定义了long int
对象的最大值为LONG_MAX
,其中LONG_MAX
必须至少为2,147,483,647
。
因此,4,294,967,294
不能由long
表示。
修复:
- 始终对
unsigned
类型执行位操作。 - 将函数的返回类型从
long
更改为unsigned
。 - 使用
stdint.h
头文件中定义的int32_t
和int64_t
等类型,这些类型分别保证具有32
位和64
位。
英文:
On some platforms, sizeof long == sizeof int
.
The standard defines the maximum value for an object of a long int
to be LONG_MAX
, where LONG_MAX
must be at least 2,147,483,647
.
Thus, 4,294,967,294
can't be represented by a long
.
Fix:
- Always do bitwise operations on
unsigned
types. - Change the return type of the function from
long
tounsigned
. - Use types like
int32_t
andint64_t
defined instdint.h
header file, which are guaranteed to have32
and64
bits respectively.
答案2
得分: 1
~
应用于一个类型为有符号 long
的操作数 n
。假设长整型为32位,那么它的二进制表示将变为 11111111 11111111 11111111 11111110
。但在十进制表示中,这意味着 -2
,因为绝大多数实际计算机使用的是 二进制补码。
当转换为 unsigned long
时,它确实变为 4294967294
,因为这是有符号到无符号的转换方式。
> 我得到了 -2 作为结果。
返回时,你再次将其转换为有符号数。这种转换是与实现相关的,但在所有主流系统上,你很可能会再次得到 -2
。类似地,如果你尝试使用 printf(""%ld"", my_unsigned_long)
打印一个 unsigned long
,那么它很可能会显示存储在 unsigned long
中的带符号十进制表示。
> 所以我只是使用了异或操作,它起作用了
在32位系统的情况下,n ^ 4294967295
的操作数之一,即常数 4294967295
,是类型为 long long
的,因为它不能适应任何较小的类型。当编译器尝试确定要用于 4294967295
的类型时,它会自问:它能适应一个 int
吗?不能。它能适应一个 long
吗?不能。它能适应一个 long long
吗?能。
因此,1 ^ 4294967295
得到了预期的 4294967294
,因为计算是在类型 long long
上进行的,没有任何影响到符号位。
英文:
~
is applied on an operand n
which is of type signed long
. Assuming 32 bit long then binary it will become 11111111 11111111 11111111 11111110
indeed. But in decimal representation that means -2
since the vast majority of real-world computers use two's complement.
When converted to unsigned long
it does become 4294967294
however, because that's how signed to unsigned conversion works.
> I got -2 as result.
Upon return you convert back to signed again. This conversion is implementation-defined but likely you'll end up with -2
again on all mainstream system. Similarly, if you would attempt to print an unsigned long
using printf("%ld", my_unsigned_long)
then it will likely display the signed decimal representation of what's stored inside the unsigned long
.
> So then I just used XOR operation and it worked
In case of a 32 bit system, then one operand of n ^ 4294967295
, namely the 4294967295
constant, is of type long long
- because it can't fit in any smaller type. When the compiler tries to determine what type it will use for 4294967295
, it will ask itself: Does it fit inside an int
? No. Does it fit inside a long
? No. Does it fit inside a long long
? Yes.
Therefore 1 ^ 4294967295
gives 4294967294
as expected, since the calculation is carried out on type long long
and nothing affects the sign bit.
答案3
得分: 0
在使用位运算符之前,您必须考虑以下几个方面:
- 一些填充位的组合可能会生成陷阱表示。N1256脚注
- 二进制补码不是唯一编码整数的方式。N1256 6.2.6.2
为了满足上述要求,我们使用uintN_t
而不是long
。intN_t
没有填充位,而uintN_t
是二进制补码表示法。这里的N
表示宽度。例如,int8_t
表示具有精确宽度为8位的有符号整数类型。唯一的问题是uintN_t
是可选的。N1256 7.18.1.1
> 为什么C中的1的~操作不表示为4294967294而表示为-2?如果可能的话,我需要做什么才能使~运算符返回4294967294而不是-2?
4294967294等于UINT32_MAX - 1
。因此,我们选择了uint32_t
。
uint32_t flippingBits(uint32_t n)
{
return ~n;
}
英文:
Before using bitwise operators, you must consider several things :
- Some combinations of padding bits might generate trap representations. N1256 footnote
- Two's complement is not the only way to encode a integer. N1256 6.2.6.2
To satisfy above requirments, we use uintN_t
instead of long
. intN_t
doesn't have padding bits. And uintN_t
is two's complement representation. N
stands for width. For example, int8_t
denotes a signed integer type with a width of exactly 8 bits. The only problem is uintN_t
is optional. N1256 7.18.1.1
> Why ~ operation of 1 not represented as 4294967294 but -2 in C? What do I need to do to make ~ operator return 4294967294 and not -2 (if it's possible)?
4294967294 is equal to UINT32_MAX - 1
. So we choose uint32_t
.
uint32_t flippingBits(uint32_t n)
{
return ~n;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论