x是一个int,
当不涉及0时,我应该能够得到正确的结果。为了解释0案例,我添加了"& x",我相信现在应该返回一个数字是正数iff x> 0和x不为0(因为在c中,0以外的任何数字的计算结果为真,对吗?)
但是,在运行我的测试时,它说它无法将0x7fffffff评估为正,我不确定为什么!
这是我的代码:
int mask = 0x1;
x = x >> 31;
int lsb = mask & x;
return ( (lsb) ^ 0x1) & (x) )
编辑:我已经通过将代码更改为下面的代码解决了问题!反馈仍然非常受欢迎,或者您可能发现任何问题。
int mask = 0x1;
int lsb = (x >> 31) & mask;
int result = !(lsb ^ 0x1);
return !(result | !x);
答案 0 :(得分:1)
https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign
从技术上讲,int
在不同的机器上可能有不同的大小;使用来自int32_t
的C99 inttypes.h
可能有助于提高可移植性。它甚至可能不会以您期望的格式进行编码,Are there any non-twos-complement implementations of C?。
真正便携的简单方法当然是
static int is_positive(const int a) {
return a > 0;
}
编译器可能会更好地优化它。
编辑:从评论中,我想出了这个;我试图让它与int
- 大小无关。它与您自己的风格非常相似,检查数字是负数还是零,并反转。
#include <stdio.h> /* printf */
#include <limits.h> /* INT_ */
#include <assert.h> /* assert */
/** Assumes a is a 2's-compliment number
and ~INT_MAX = 0b100..00, (checks if negative.) */
static int is_positive(const int a) {
unsigned b = a;
return !((b & ~INT_MAX) | !b);
}
static int is_really_positive(const int a) {
return a > 0;
}
static void test(const int a) {
printf("Number %d. Is positive %d.\n", a, is_positive(a));
assert(is_positive(a) == is_really_positive(a));
}
int main(void) {
test(INT_MIN);
test(-2);
test(-1);
test(0);
test(1);
test(2);
test(INT_MAX);
return 0;
}
答案 1 :(得分:1)
如果你知道代表是2's complement,那么你可以这样做:
#include <stdio.h>
#define IS_NEG(a) (!!((1 << 31) & (a)))
int main(void)
{
int n;
while(1) {
scanf("%d", &n);
printf("negative: %d\n", IS_NEG(n));
}
return 0;
}
说明:
(1 << 31)
将获取数字1并将其向左移动31次,从而为您提供1000 0000 0000 0000 0000 0000 0000 0000
。如果您不想使用班次,也可以使用0x80000000
。& (a)
使用那个大二进制数进行逐位测试。由于AND操作仅在两个操作数均为TRUE
时返回TRUE
,因此只有当您的数字为负数(在2&#39的补码表示中)时才会返回返回TRUE
。!!(...)
这个双重否定说明了这样一个事实:当你按位进行AND时,如果数字真的是负数,表达式的返回值将是(1 << 31)
。所以我们将它反转(给我们零),而不是再反转它(给我们1)。因此,这可以确保我们获得ZERO或ONE作为最终结果。IS_NEG
将在正数AND 0上返回0,并在所有负数上返回1。 由于当数字为负数时MSB将为1,因此只需测试该位。请注意,这仅适用于32位整数(因此您必须使用sizeof(int)
进行检查。如果数字为负数,则示例返回1,但将其重新编译为没有问题返回1表示正数。
如果这不能解决问题,请告诉我。据我了解,您只想测试任何给定的int
是否为正/负。
#include <stdio.h>
#define IS_NEG(a) (!!(0x80000000 & (a)))
char buf[65];
/* converts an integer @n to binary represention of @bits bits */
char *bin(int n, unsigned int bits)
{
char *s = buf;
for(bits = (1 << (bits - 1)); bits > 0; bits = bits >> 1)
/* look! double negation again! Why this? :) */
*s++ = !!(n & bits) + 48;
*s = 0;
return buf;
}
int main(void)
{
/* R will be our partial result through-out the loop */
int r, n;
while(1) {
/* get the number */
scanf("%d", &n);
/* this is the inner part of the macro
* after this, we could say IS_NEG "becomes"
* (!!(r))
*/
r = n & 0x80000000;
printf("n & 0x80000000: 0x%x\n", r);
printf(" n = %s\n", bin(n, 32));
printf(" r = %s\n", bin(r, 32));
/* now we print what R is, so you see that the bitwise AND will
* return 0x80000000 on negative numbers. It will also print
* the NEGATION of R...
*
* After the printf(), we just assign the negated value to R.
*/
printf("r = 0x%x, !r = 0x%x\n", r, !r);
r = !r;
printf(" r = %s\n", bin(r, 32));
/* After this, IS_NEG "becomes" (!(r)) */
/* In the MACRO, this would be the second negation. */
printf("r = 0x%x, !r = 0x%x\n", r, !r);
r = !r;
printf(" r = %s\n", bin(r, 32));
/* Now, if R is 0, it means the number is either ZERO or
* POSITIVE.
*
* If R is 1, then the number is negative
*/
}
return 0;
}
答案 2 :(得分:1)
鉴于您的评论中允许的运算符! ~ & ^ | + << >>
,编辑:使用后来的无强制转换约束,只有第二种替代方案适合:
static int is_positive(unsigned x)
{
return ~x+1 >> (CHAR_BIT*sizeof x-1);
}
这里是交易:在C中非常仔细地指定转换为无符号:如果无符号类型中的有符号值不可表示,则添加一个加上无符号类型中可表示的最大值(或减去,不知道)是什么促使他们将这种可能性包括在传入的值中,直到结果 可表示为止。
因此结果仅取决于传入值,而不是其表示。无论怎样,-1都会转换为UINT_MAX。这是正确的,因为the universe itself runs on twos-complement notation。这也使得转换成为大多数CPU上的简单无操作重新解释只是一个奖励。
答案 3 :(得分:0)
您可以使用按位或移位进行32位宽零或非零测试,如下所示:
int t;
t = x | (x>>16);
t = t | (t >> 8);
t = t | (t >> 4);
t = t | (t >> 2)
t = (t | (t>>1)) & 1;
这将t
设置为x的低32位的“OR”,并且当且仅当低32位全为零时才为0。如果int
类型为32位或更少,则相当于(x != 0)
。您可以将它与您的符号位测试结合起来:
return t & (~x >> 31);
答案 4 :(得分:0)
检查给定数字是正数还是负数。正如您所提到的,x
是int
&amp;我假设它的32位长签名int。例如
int x = 0x7fffffff;
以上x
如何用二进制
x => 0111 1111 | 1111 1111 | 1111 1111 | 1111 1111
| |
MSB LSB
现在使用按位opaertor检查给定数字是正数还是负数,只需找出最后状态(MSB或31st(longint)或第15(short int))位状态,无论是0
还是{{1如果找到最后一位为1
,则表示给定数字为正数,否则为负数。
现在如何检查最后一位(第31位)状态?将最后(第31位)位移到0
位并执行按位AND&amp;使用0th
进行操作。
1
现在如何编程
x => 0111 1111 | 1111 1111 | 1111 1111 | 1111 1111
x>>31 => 0000 0000 | 0000 0000 | 0000 0000 | 0000 0000
---------------------------------------------
&
1 => 0000 0000 | 0000 0000 | 0000 0000 | 0000 0001
---------------------------------------------
0000 0000 | 0000 0000 | 0000 0000 | 0000 0000 => its binary of zero( 0 ) so its a positive number
并调用static inline int sign_bit_check(int x) {
return (x>>31) & 1;
}
之类的
sign_bit_check()