Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 位除法舍入到最接近的零_C_Math_Bit Manipulation - Fatal编程技术网

C 位除法舍入到最接近的零

C 位除法舍入到最接近的零,c,math,bit-manipulation,C,Math,Bit Manipulation,我想执行有符号整数按2的幂进行位除。然而,我遇到了几个问题。我只是想知道是否有人能帮我 首先,我尝试单独使用位移位: int result = number >> n; 然而,当我尝试除以一个负数时,我遇到了一个问题。(它总是用一个更大的数字取整。例如:-9/4=-3而不是-2。因此,我在互联网上查找这个问题,最终得到了以下解决方案: int result = (number + (1<<n)-1) >> n; int结果=(数字+(1 n; 但是,当我

我想执行有符号整数按2的幂进行位除。然而,我遇到了几个问题。我只是想知道是否有人能帮我

首先,我尝试单独使用位移位:

int result = number >> n;
然而,当我尝试除以一个负数时,我遇到了一个问题。(它总是用一个更大的数字取整。例如:-9/4=-3而不是-2。因此,我在互联网上查找这个问题,最终得到了以下解决方案:

int result = (number + (1<<n)-1) >> n;
int结果=(数字+(1 n;
但是,当我尝试11/4=3而不是2时


有什么建议吗?我只能使用!~&^ |+>(没有循环或如果允许/开关)

也许这会对您有所帮助

1) 如果您使用的是
/
运算符,则标准规定(
ISO/IEC TR3 in 6.5.5乘法运算符中的
/
)运算符的结果是第一个操作数除以第二个操作数的商

2) 如果您使用的
>
标准规定(
6.5.7中的ISO/IEC TR3
)是LHS操作数为有符号类型且为负数的
的结果,则结果值为
实现定义的

因此,
/
将为您提供所需的结果


但是有符号和负数上的
取决于编译器。

以下方法不好,因为它依赖于:

  • 负整数的右移是算术移位(可能不是这种情况)
  • 符号整数是2的补码表示(极少数情况下可能不是这种情况)
  • 没有任何填充位的整数(现在在现代CPU上你找不到填充位,尽管标准允许它们的存在)
由于有符号整数溢出,它可能会导致某些红利(例如,
INT\u MIN
)出现未定义的行为

因此,它不可移植,也不能保证始终工作。您已收到警告

#include <stdio.h>
#include <limits.h>

int DivByShifting1(int n, unsigned shift)
{
  int sgn = n >> ((sizeof(int) * CHAR_BIT) - 1);
  return ((((n + sgn) ^ sgn) >> shift) + sgn) ^ sgn;
}

int main(void)
{
  int n, s;
  for (n = -10; n <= 10; n++)
    for (s = 0; s <= 4; s++)
      printf("%d / %d = %d\n", n, 1 << s, DivByShifting1(n, s));
  return 0;
}
请注意,
((sizeof(int)*CHAR_BIT)-1)
是编译时常量,因此可以允许
*
-

另一个版本非常类似,但不要求负整数的右移位为算术移位,并且不存在有符号整数溢出(2的补码和填充位仍然是限制,但实际上在今天的实践中存在):

@R.正确地提醒,从
有符号整数
无符号整数
的转换可以通过添加0u(无符号0)来完成


他还提醒说,可以直接返回
un
,而不必执行
memcpy()
n
。转换应该由实现定义,但在C的2的补码实现中,比特对比特的复制实际上总是如此。

只需使用
//code>操作符:

int result = number / (1 << n);

intresult=number/(1从
intdiv(inta){returna/4;}
的反汇编判断:

leal 3(%rdi), %eax
testl %edi, %edi
cmovns %edi, %eax
sarl $2, %eax

必须通过
(1n)
调整操作数;这两种操作数都可以根据实现定义的行为使用无分支的bitmagic实现。

我不清楚。1)您是使用
/
获得结果,还是2)使用
执行等效除法?@Koushik,他说他只能使用这些操作符:!~&^ |+>。另外,没有循环或if条件/开关。@Koushik我正在调用一个函数div(11,2)来执行11/4@AnishRam我只是想确保他不会漏掉
/
。现在我很清楚了。一个有用的链接,你能解释一下
n>>((sizeof(int)*CHAR_位)-1)
在你的
DivByShifting1
函数中做了什么吗?@AnishRam。它为n>=0提供了0,为n<0提供了-1。就我个人而言,我会使用实现定义的从
无符号
int
的转换(发生在
返回
语句中)与其说
memcpy
…不如说练习的重点是避免在源代码中进行显式除法。那么我认为这是不可移植的,因为
>
是为负操作数定义的实现。您至少需要一种方法来根据操作数是否为负来调节表达式……或者它将使用
idiv
;您可以将有符号整数强制转换为无符号整数,并使用最高有效位作为符号位值。我认为,它仍然是可行的,尽管要长得多。是的,刚刚添加了一个版本,不依赖于
>
的实现定义行为。
-10 / 1 = -10
-10 / 2 = -5
-10 / 4 = -2
-10 / 8 = -1
-10 / 16 = 0
-9 / 1 = -9
-9 / 2 = -4
-9 / 4 = -2
-9 / 8 = -1
-9 / 16 = 0
-8 / 1 = -8
-8 / 2 = -4
-8 / 4 = -2
-8 / 8 = -1
-8 / 16 = 0
-7 / 1 = -7
-7 / 2 = -3
-7 / 4 = -1
-7 / 8 = 0
-7 / 16 = 0
-6 / 1 = -6
-6 / 2 = -3
-6 / 4 = -1
-6 / 8 = 0
-6 / 16 = 0
-5 / 1 = -5
-5 / 2 = -2
-5 / 4 = -1
-5 / 8 = 0
-5 / 16 = 0
-4 / 1 = -4
-4 / 2 = -2
-4 / 4 = -1
-4 / 8 = 0
-4 / 16 = 0
-3 / 1 = -3
-3 / 2 = -1
-3 / 4 = 0
-3 / 8 = 0
-3 / 16 = 0
-2 / 1 = -2
-2 / 2 = -1
-2 / 4 = 0
-2 / 8 = 0
-2 / 16 = 0
-1 / 1 = -1
-1 / 2 = 0
-1 / 4 = 0
-1 / 8 = 0
-1 / 16 = 0
0 / 1 = 0
0 / 2 = 0
0 / 4 = 0
0 / 8 = 0
0 / 16 = 0
1 / 1 = 1
1 / 2 = 0
1 / 4 = 0
1 / 8 = 0
1 / 16 = 0
2 / 1 = 2
2 / 2 = 1
2 / 4 = 0
2 / 8 = 0
2 / 16 = 0
3 / 1 = 3
3 / 2 = 1
3 / 4 = 0
3 / 8 = 0
3 / 16 = 0
4 / 1 = 4
4 / 2 = 2
4 / 4 = 1
4 / 8 = 0
4 / 16 = 0
5 / 1 = 5
5 / 2 = 2
5 / 4 = 1
5 / 8 = 0
5 / 16 = 0
6 / 1 = 6
6 / 2 = 3
6 / 4 = 1
6 / 8 = 0
6 / 16 = 0
7 / 1 = 7
7 / 2 = 3
7 / 4 = 1
7 / 8 = 0
7 / 16 = 0
8 / 1 = 8
8 / 2 = 4
8 / 4 = 2
8 / 8 = 1
8 / 16 = 0
9 / 1 = 9
9 / 2 = 4
9 / 4 = 2
9 / 8 = 1
9 / 16 = 0
10 / 1 = 10
10 / 2 = 5
10 / 4 = 2
10 / 8 = 1
10 / 16 = 0
int result = number / (1 << n);
leal 3(%rdi), %eax
testl %edi, %edi
cmovns %edi, %eax
sarl $2, %eax