相关疑难解决方法(0)

在C/C++中获得正模数的最快方法

通常在我的内部循环中,我需要以"环绕"方式索引数组,因此如果数组大小为100并且我的代码要求元素-2,则应该给出元素98.在许多高级语言中作为Python,人们可以简单地使用my_array[index % array_size],但由于某种原因,C的整数运算(通常)向零舍入而不是一致向下舍入,因此当给定负的第一个参数时,其模运算符返回负结果.

通常我知道这index不会少于-array_size,在这些情况下我只是这样做my_array[(index + array_size) % array_size].但是,有时这无法得到保证,对于那些情况,我想知道实现始终为正模数函数的最快方法.有几种"聪明"的方法可以在没有分支的情况下完成,例如

inline int positive_modulo(int i, int n) {
    return (n + (i % n)) % n;
}
Run Code Online (Sandbox Code Playgroud)

要么

inline int positive_modulo(int i, int n) {
    return (i % n) + (n * (i < 0));
}
Run Code Online (Sandbox Code Playgroud)

当然,我可以对这些进行分析,以找出哪个是我系统中最快的,但我不禁担心我可能错过了一个更好的,或者我的机器上的速度可能在另一个机器上很慢.

那么有没有一种标准的方法可以做到这一点,或者一些我错过的聪明技巧可能是最快的方式?

此外,我知道这可能是一厢情愿的想法,但如果有一种方法可以自动矢量化,那将是惊人的.

c c++ performance

56
推荐指数
5
解决办法
3万
查看次数

有符号整数上的算术位移

我试图弄清楚算术位移运算符在C中是如何工作的,以及它将如何影响带符号的32位整数.

为简单起见,假设我们在一个字节(8位)内工作:

x = 1101.0101
MSB[ 1101.0101 ]LSB
Run Code Online (Sandbox Code Playgroud)

在Stack Overflow和一些网站上阅读其他帖子,我发现: <<将转向MSB(在我的情况下向左),并用0填充"空"LSB位.

>>会向着转向LSB(向右,在我的情况),并填写"空"与MS位位

因此,x = x << 7将导致LSB移动到MSB,并将所有内容设置为0.

1000.0000
Run Code Online (Sandbox Code Playgroud)

现在,让我说我会>> 7,最后的结果.这会导致[0000.0010]?我对吗?

关于转移运营商我的假设是对的吗?

我刚在我的机器上测试过,**

int x = 1;   //000000000......01

x = x << 31; //100000000......00

x = x >> 31; //111111111......11 (Everything is filled with 1s !!!!!) 
Run Code Online (Sandbox Code Playgroud)

为什么?

c bit-manipulation

53
推荐指数
4
解决办法
8万
查看次数

什么是(x&1)和(x >> = 1)?

我正在尝试分配:"在不使用sizeof()函数的情况下查找无符号整数数据类型中的位数."

我的设计是将整数转换为位然后计算它们.对于前:10 is 10105 is 101

将整数转换为位表示形式显示如下:

do
{ 
    Vec.push_back( x & 1 ) 
} 
while ( x >>= 1 );
Run Code Online (Sandbox Code Playgroud)

我不想只是复制粘贴的东西.当我使用F-10时,我看到(x & 1)正在做什么,但我不知道它是名字还是它如何完成它的工作(比较一些东西?).我也知道>=哪个"大于或等于"但是什么x >>= 1

注意:标记的副本是JavaScript而不是C++

c++ bit-manipulation bit-shift bitwise-operators bitwise-and

38
推荐指数
4
解决办法
7万
查看次数

为什么((unsigned char)0x80)<< 24将符号扩展为0xFFFFFFFF80000000(64位)?

以下程序

#include <inttypes.h> /*  printf(" %" PRIu32 "\n"), my_uint32_t) */
#include <stdio.h> /* printf(), perror() */

int main(int argc, char *argv[])
{
  uint64_t u64 = ((unsigned char)0x80) << 24;
  printf("%"  PRIX64 "\n", u64);

  /* uint64_t */ u64 = ((unsigned int)0x80)  << 24;
  printf("%016"  PRIX64 "\n", u64);
}
Run Code Online (Sandbox Code Playgroud)

产生

FFFFFFFF80000000
0000000080000000
Run Code Online (Sandbox Code Playgroud)

是什么区别((unsigned char)0x80),并((unsigned int)0x80)在这方面?

我想这(unsigned char)0x80会被提升到(unsigned char)0xFFFFFFFFFFFFFF80然后有点转移,但为什么这种转换认为unsigned char是签名?

值得注意的是,它0x80 << 16会产生预期的结果0x0000000000800000.

c bit-manipulation

34
推荐指数
4
解决办法
3163
查看次数

在某个位置或更低位置计算设置位的有效方法是什么?

给定std::bitset<64> bits任意数量的位和位位置X(0-63)

在X位或更低位计数位的最有效方法是什么,如果未设置X位,则返回0

注意:如果设置该位,则返回始终至少为1

蛮力方式很慢:

int countupto(std::bitset<64> bits, int X)
{
  if (!bits[X]) return 0;
  int total=1;
  for (int i=0; i < X; ++i)
  {
    total+=bits[i];
  }
  return total;
}
Run Code Online (Sandbox Code Playgroud)

这个count()方法bitset将为您popcount提供所有位,但bitset不支持范围

注意:这不是如何计算32位整数中的设置位数?因为它询问所有位而不是0到X的范围

c++ algorithm performance bit-manipulation

33
推荐指数
4
解决办法
5006
查看次数

签名右移:哪个编译器使用逻辑移位

我使用Visual Studio,Ubuntu的GCC,英特尔编译器,MinGW测试了右移.所有移位的符号位.我猜Xcode的GCC也是如此.

我知道这种行为是特定于实现的,但看起来所有主要的桌面/服务器编译器都实现了算术移位.是否有任何广泛使用的编译器不会在符号位中移位?

谢谢.

c c++

11
推荐指数
1
解决办法
6010
查看次数

存储负数

在下面的代码中

int main()
{
int  a = -1;
printf("%d",a>>1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么它给出输出-1.

c

9
推荐指数
2
解决办法
1964
查看次数

C中〜0的值是多少?

我想要得到的价值INT_MININT_MAX,和我试过~0~0 >> 1,因为最左边的位为符号位.我得到了他们两个-1.

它太混乱了,为什么不~0成为0xffffffff~0 >> 1将来0x7fffffff

c bit-manipulation

9
推荐指数
1
解决办法
3285
查看次数

正数和负数的按位运算符

    -5 / 2 = -2

    -5 >> 1 = -3
Run Code Online (Sandbox Code Playgroud)

我向老师学习>> 1将数字除以2.它对正数有效,但对负数不起作用.有人可以向我解释一下吗?

谢谢

c++ bitwise-operators

8
推荐指数
2
解决办法
1万
查看次数

为什么在C中右移负数会使最左边的位数为1?

赫伯特·希尔特(Herbert Schildt)的书"C完整参考文献"中说"(在有符号的负整数的情况下,右移将导致1被引入,以便保留符号位.)"

保留标志位有什么意义?

此外,我认为这本书是指使用符号位表示负数而不使用二进制补码的情况.但即使在这种情况下,推理似乎也没有任何意义.

c bit-manipulation bit-shift

6
推荐指数
2
解决办法
3万
查看次数