- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在编写一个计算参数 x 的 2 倍的函数,但如果它溢出,它应该返回最大的正数或负数。问题是我只能使用 ! ~ & ^ | + << >>
.涉及 32 位整数。
这是我目前所拥有的:
int boundedMult(int x){
int xSign = x>>31
int y = x << 1; // Multiply by 2
int signBit = y>>31; // Capture the signBit of the answer
int shift = signBit;
shift |= shift<<1; // Make shift all 1 or 0 depending on the sign bit
shift |= shift<<2;
shift |= shift<<4;
shift |= shift<<8;
shift |= shift<<15;
int answer = ~signBit<<31 | shift; // 01111... If signBit=1 and 1000... If signBit=0
}
看起来不错,对吧?我也不能使用无符号字节 (0-255) 以外的任何常量,包括在内。我尝试了很多方法,但最终我在所有这些方法中都违反了其中一条规则。
最佳答案
有趣的挑战!这是我的解决方案,我希望我没有错误地违反任何约束:
#include <stdio.h>
#include <stdint.h>
// work with uint to avoid undefined behavior (signed int overflow is undefined)
static inline int32_t x2(int32_t v) {
uint32_t uv = v;
// our first option: "multiply" by shifting:
uint32_t doubled = uv<<1;
// our second option: clamp to max/min integer:
uint32_t neg = !!(uv >> 31); // 1 if negative
uint32_t bigval = (~0u)>>1; // 0x7fffffff
uint32_t clamped = bigval + neg; // 0x80000000 if neg, 0x7fffffff otherwise
// so, which one will we use?
uint32_t ok = !((v>>31) ^ (v>>30)); // 0 if overflow, 1 otherwise
// note the use of signed value here
uint32_t mask = (~ok)+1; // 0x00000000 if overflow, 0xffffffff otherwise
// choose by masking one option with ones, the other with zeroes
return (mask & doubled) | ((~mask) & clamped);
}
static inline void check(int32_t val, int32_t expect) {
int32_t actual = x2(val);
if ((val & 0x3ffffff) == 0) {
printf("0x%08x...\n", val);
}
if (actual != expect) {
printf("val=%d, expected=%d, actual=%d\n", val, expect, actual);
}
}
int main() {
int32_t v = 0x80000000;
printf("checking negative clamp...\n");
for (; v < -0x40000000; ++v) {
check(v, 0x80000000);
}
printf("checking straight double...\n");
for(; v < 0x40000000; ++v) {
check(v, 2*v);
}
printf("checking positive clamp...\n");
for(; v < 0x7fffffff; ++v) {
check(v, 0x7fffffff);
}
check(0x7fffffff, 0x7fffffff);
printf("All done!\n");
return 0;
}
它似乎工作正常:
gcc -std=c99 -O2 -Wall -Werror -Wextra -pedantic bounded.c -o bounded && ./bounded
checking negative clamp...
0x80000000...
0x84000000...
0x88000000...
0x8c000000...
0x90000000...
0x94000000...
0x98000000...
0x9c000000...
0xa0000000...
0xa4000000...
0xa8000000...
0xac000000...
0xb0000000...
0xb4000000...
0xb8000000...
0xbc000000...
checking straight double...
0xc0000000...
0xc4000000...
0xc8000000...
0xcc000000...
0xd0000000...
0xd4000000...
0xd8000000...
0xdc000000...
0xe0000000...
0xe4000000...
0xe8000000...
0xec000000...
0xf0000000...
0xf4000000...
0xf8000000...
0xfc000000...
0x00000000...
0x04000000...
0x08000000...
0x0c000000...
0x10000000...
0x14000000...
0x18000000...
0x1c000000...
0x20000000...
0x24000000...
0x28000000...
0x2c000000...
0x30000000...
0x34000000...
0x38000000...
0x3c000000...
checking positive clamp...
0x40000000...
0x44000000...
0x48000000...
0x4c000000...
0x50000000...
0x54000000...
0x58000000...
0x5c000000...
0x60000000...
0x64000000...
0x68000000...
0x6c000000...
0x70000000...
0x74000000...
0x78000000...
0x7c000000...
All done!
使用 this handy interactive compiler ,我们可以得到各种平台的反汇编。带注释的 ARM64 程序集:
x2(int):
asr w1, w0, 30 # w1 = v >> 30
cmp w1, w0, asr 31 # compare w1 to (v>>31)
csetm w1, eq # w1 = eq ? 0 : -1
# --- so w1 is "mask"
mov w2, 2147483647 # w2 = 0x7fffffff
mvn w3, w1 # w3 = ~w1
# --- so w3 is ~mask
add w2, w2, w0, lsr 31 # w2 = w2 + (v>>31)
# --- so w2 is "clamped"
and w2, w3, w2 # w2 = w3 & w2
and w0, w1, w0, lsl 1 # w0 = w1 & (v << 1)
orr w0, w2, w0 # w0 = w2 | w0
ret # return w0
在我看来效率很高。非常棒的是,“doubled”永远不会保存到寄存器中——它只是作为 和 指令之一的输入值的移位完成的。
关于c - C 中的 Bit Twiddling - 计算 2 倍 x 或返回最大有符号数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36113495/
我正在努力弄清楚如何在参数优化方法上设置界限(最小/最大)。 Twiddle是优化算法:https://www.youtube.com/watch?v=2uQ2BSzDvXs .我怎样才能确保 p(参
我的 twiddle 有问题Solaris 10 服务器上的脚本。 我必须阅读一些属性,例如 jboss.system和别的。 取决于 jboss 服务器的所有属性都很好,但是当我尝试时 从 java
所以我在 C 中摆弄 Bit-Twiddling,我遇到了一个有趣的输出: int main() { int a = 0x00FF00FF; int b = 0xFFFF0000;
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve thi
想知道是否有人对我如何对二进制数执行以下操作有一些了解: 转换 01+0 -> 10+1 (+ as in regular expressions, one or more) 01 ->
我喜欢看到人们编写 Bit Twiddling 代码,但我根本无法理解它。经历了黑客的喜悦和http://graphics.stanford.edu/~seander/bithacks.html ,但
假设我们有一个 8 字节的 ulong。对于每个字节,我们想知道它是零还是非零。期望的结果是一个字节,其 8 位表示原始 8 个字节的“非零”。 是否有这个操作或一组操作的名称? 我们如何才能非常有效
摘要 您好,假设您有两个不同的独立 64 位二进制矩阵 A 和 T(T 是另一个存储在转置矩阵中的矩阵形式,使用矩阵的转置版本允许在乘法期间对 T 的行而不是列进行操作,这对于二进制算术来说非常酷)并
考虑以下问题。您有一个位串,表示单热编码中的当前预定从站。例如,“00000100”(最左边的位是#7,最右边的位是#0)表示从机#2 已被调度。 现在,我想在循环调度方案中选择下一个预定的从站,但要
我问是否有可能显着改进整数矩阵乘法 bitwise operations .矩阵很小,元素是小的非负整数(小意味着最多 20)。 为了让我们集中注意力,让我们非常具体,假设我有两个 3x3 矩阵,整数
我需要制作一个不涉及循环(仅位操作)并且不使用大常量的字中的位计数例程。 int x = 0xFFFFFFFF; x += (~((x >> 1) & 0x55555555)+1); x = (((x
我想在 ember-twiddle 上创建一个演示.但我不能使用它的一些插件,特别是 ember-moment添加在。 如何使用 ember-moment 创建演示添加在? 最佳答案 在 twiddl
代码如下: unsigned int v; // word value to compute the parity of v ^= v >> 16; v ^= v >> 8; v ^= v >> 4
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
感谢 Bit twiddling: which bit is set? 上的一些非常有帮助的 stackOverflow 用户,我已经构建了我的函数(发布在问题的末尾)。 任何建议——即使是很小的建议
我有一个位计数方法,我正试图尽快完成。我想从 Bit Twiddling Hacks 尝试下面的算法,但我不知道 C。什么是“类型 T”以及 (T)~(T)0/3 的 python 等价物是什么? A
我正在编写一个计算参数 x 的 2 倍的函数,但如果它溢出,它应该返回最大的正数或负数。问题是我只能使用 ! ~ & ^ | + > .涉及 32 位整数。 这是我目前所拥有的: int bounde
我见过在 ruby 的 gem 文件 (documentation) 中使用的 twiddle-wakka 运算符 (~>) 来指定兼容的最后一 pip 版本,如下所示: '~> 0.3.1' i
我是一名优秀的程序员,十分优秀!