在我的程序中,我在循环中有如下语句。
y = (x >= 1)? 0:1;
但是,我想避免使用任何关系运算符,因为我想使用SIMD指令,并且不确定关系运算符是否适用于SIMD。
我想要以下内容。
a = some_operation(x) // a will be either 1 or 0
y = 1 - a
some_operation
将任何等于或大于1的数字转换为1,并将0保持为0.因此,我的问题是,是否有任何some_operation
可以实现我的目的?
答案 0 :(得分:3)
如果在不使用任何关系运算符的情况下将整数转换为1,有没有办法将整数转换为1?
对于 unsigned 整数,您只需执行以下操作:
unsigned int i = 42; // ... or any other value > 0.
unsigned int j = !!i; // j is 1 here.
i = 0;
j = !!i; // j is 0 here.
更新
对于签名的整数,您可以执行
int i = ...
int j = !!(i * !((1 << ((CHAR_BITS * sizeof i) - 1)) & i));
以上行导致
0
的i < 1
任何1
i >= 1
答案 1 :(得分:3)
#define INT_BITS (CHAR_BIT * sizeof(int))
int make_zero_or_one(int x) {
return 1 - (((x-1) >> (INT_BITS-1)) & 1);
}
与其他答案一样,这取决于MSB是整数中的符号位。对于所有整数,该函数返回0&lt; = 0,否则返回1。如果x-1
溢出,该函数将失败。
此实现在编译代码中没有分支。
答案 2 :(得分:2)
假设您使用两个补码,您可以这样做。 (使用的另一个答案!! x可能是也可能不是你想要的,取决于计算机的指令集以及你想避免关系运算符的原因)
int x = 42; // or any integer
int test = x-1;
if(test & 1 << (CHAR_BIT * sizeof(int) -1))
{
// integer negative or zero
}
else
{
// integer positive
}
答案 3 :(得分:1)
我知道这个答案明确地与你的问题相矛盾,但是在所有常见的SIMD架构上都有SIMD比较(至少我知道)。
对于SSE2和int32
参数,有pcmpgtd
(内在:_mm_cmpgt_epi32
),假设您在__m128i x
中有4个整数,则可以写
__m128i result = _mm_cmpgt_epi32(x, _mm_setzero_si128())
要为-1
(即0xFFFFFFFF
}和x>0
获取x>=1
(即0
)。如果您需要1
而非-1
,只需撰写
__m128i y = _mm_sub_epi32(_mm_setzero_si128(), result);
答案 4 :(得分:-1)
我不熟悉C或使用SIMD指令,但如果x是正整数,那么你不能这样做吗?
y = (x == 0) ? 1 : 0;
答案 5 :(得分:-1)
使用此:y= 1/(1+e^(-10000*(x-0.995)))
这将提供y = 0 for x <= 0.99
和y=1 for x>= 1
我不知道SIMD是什么,有很好的方法可以做到这一点。但我想,如果你不想使用条件,你可以使用sigmoid函数,根据你的标准返回0或1。此函数将是您的some_operation(x)
。注意此函数仅适用于包含2位小数的数字。也就是说,输入0.99将返回0但输入0.999将返回1.确保在执行计算之前将数字向下四舍五入到最接近的2位小数。
如果有兴趣的话,我将在下面逐步完成我的思考过程:
如果你想使用一个函数,而不是一个逻辑条件,它必须是连续的,根据定义,这意味着值的som不符合标准。但如果这些数值在一个非常狭窄的范围内,并且你的数字之间的步数大于那个狭窄的范围,它就会起作用。
所以你可以使用sigmoid函数。 (将其输入到wolfram alpha中,以便查看每个更改)
y = 1/(1+e^(-x))
然后将它向右移动一步,使其以1而不是零为中心。
y = 1/(1+e^(-(x-1)))
然后你可以通过增加重量来增加功能的斜率。
y= 1/(1+e^(-10000*(x-1)))
现在斜坡非常非常陡峭。 但是如果我们输入x = 1,我们仍然会得到y = 0.5。所以我们需要将sigmoid向左移动一点。
y= 1/(1+e^(-10000*(x-0.995)))
现在,如果x&lt; = 0.99,则y = 0,如果x> = 1,则y = 1。 如果要使用更精细的分辨率,则必须调整权重(在这种情况下为10000)和中心点(在这种情况下为0.995)。 我刚检查了wolfram alpha中的计算并迭代了什么有效。如果仅使用2位小数,则可以使用低至4000的权重。
我确定有更好的方法可以做到这一点,但这就是我解决它的方法。