相关疑难解决方法(0)

在 x86 汇编中取两个有符号整数的平均值的最快方法?

假设我们有两个寄存器长度为 2有符号1 的整数,例如ab。我们想要计算值(a + b) / 2,向上舍入、向下舍入、向零舍入或远离零舍入,无论哪种方式更容易(即我们不关心舍入方向)。

\n

结果是另一个寄存器长度有符号整数(很明显,平均值必须在寄存器长度有符号整数的范围内)。

\n

执行此计算最快的方法是什么?

\n

您可以选择两个整数最初位于哪个寄存器中,以及平均值最终位于哪个寄存器中。

\n
\n

脚注1:对于无符号整数,我们可以用两条指令来完成。尽管循环进位在 Intel CPU 上超过 1 uop,但这可能是最快的方法。但当计数仅为 1 时,只有一对。 关于无符号均值的问答中的答案讨论了效率。

\n
add rdi, rsi\nrcr rdi, 1\n
Run Code Online (Sandbox Code Playgroud)\n

rdi这两个数字以和开始rsi,平均值以 结束rdi。但对于有符号数,-1 + 3将设置 CF,并将 a 旋转1到符号位。没有给出正确答案+1

\n

脚注 2:我指定了寄存器长度的有符号整数,这样我们就不能简单地用movsxdorcdqe指令对整数进行符号扩展。

\n
\n

我得到的最接近的解决方案使用四个指令,其中一个rcr在 Intel 上为 3 uops,在 AMD …

optimization x86 assembly average micro-optimization

29
推荐指数
2
解决办法
3016
查看次数

找到两个值的平均值的正确方法是什么?

我最近了解到整数溢出是C中未定义的行为(侧面问题 - 它是否也是C++中的UB?)

经常在C语言编程,你需要找到两个值的平均值ab.但是,这样做(a+b)/2会导致溢出和未定义的行为.

所以我的问题是-什么是找到两个值的平均值的正确方法a,并b用C?

c integer-overflow undefined-behavior

17
推荐指数
3
解决办法
3498
查看次数

如何确定宽度是"int"和"unsigned"两倍的整数类型?

中间乘法的值通常需要两倍的位数作为输入.

 // Example
int foo(int a, int b, int carry, int rem) {
  int2x c;  // Some type that is twice as wide at `int`
  c = (int2x)a * b + carry;
  return (int) (c % rem);
}
Run Code Online (Sandbox Code Playgroud)

考虑到填充的可能性(似乎限制了sizeof()有用性)和非2的补码整数(限制位误),......

以下是否始终创建所需类型?
如果没有,如何编码至少一个合理的解决方案,即使不完全可移植?


#include <limits.h>
#include <stdint.h>

#if LONG_MAX/2/INT_MAX - 2 == INT_MAX
  typedef long int2x;
  typedef unsigned long unsigned2x;
#elif LLONG_MAX/2/INT_MAX - 2 == INT_MAX
  typedef long long int2x;
  typedef unsigned long long unsigned2x;
#elif INTMAX_MAX/2/INT_MAX - 2 == …
Run Code Online (Sandbox Code Playgroud)

c int portability

5
推荐指数
1
解决办法
436
查看次数