使用类似C的脚本语言实现位移运算符

问题描述 投票:1回答:4

我可以访问一个在其上运行C风格脚本语言的工具。它可以声明和使用charintdouble的变量或数组,但不能使用float。它允许标准C逻辑和加法,减法,除法和乘法的操作数。它没有有用的功能,如sizeof(),也没有任何位移运算符<<>>

我试图让它在两个二进制输出端口上发送double值。每个都可以设置为高或低。

我想我应该通过使用逐位AND比较器的双位屏蔽双值来实现这一点。但是我不能这样做,因为不存在位移操作符。然后,我将使用一个输出端口作为时钟,第二个作为同步数据线。

例如,使用值为6的输入字节(0000 0110)。数据将如下输出,X表示“时钟”向下笔划的读取值:

*Clock,  Input
* 0,     0
* 1,     0 X
* 0,     0
* 1,     1 X
* 0,     0
* 1,     1 X
* 0,     0
* 1,     0 X
* 0,     0
* 1,     0 X
* 0,     0
* 1,     0 X
* 0,     0
* 1,     0 X
* 0,     0
* 1,     0 X
* 0,     0

所以我需要一种逐位迭代的方法(不确定仪器用于其double的位数)并将输出标志设置为其值,但这不能通过位移来完成,因为我不喜欢没有它。

c bit-manipulation operators bit-shift
4个回答
1
投票

移位值相当于乘以/除以2(使用整数数学):

 a / 2   equivalent to  a >> 1 
 a * 2   equivalent to  a << 1 

您需要检查脚本语言是否进行整数数学运算(或使用floor()int()trunc()或者语言提供的语言)。

要小心溢出,如果脚本语言使用float而不是int来表示数字,你可能会发现大数字的奇怪行为。

关于签署的另一个警告。如果你必须处理负数,向左移动会更复杂。

你可以运行几个测试来检查整数的大小吗?它肯定会帮助您避免问题。


0
投票

左移1等于乘以2,右移1等于(整数)除以2.因此,左移3等于乘以8(因为它是23)。

#include <stdio.h>

int main() {
  int a = 17 << 4;
  int b = 17 * 16;

  if (a == b) {
    printf("%i\n", b);
  } else {
    puts("false");
  }
}

输出是

272

0
投票

假设您要检索的测量值确实是双倍的:如果您知道测量的允许范围,我会将它们乘以0xFFFFFFFF/MAX_RANGE因子,得到0到int max之间的值。

那你可以做

long int value = double*FACTOR;
for (i=0;i<32;i++) {
    long int nextval = value / 2;
    char bit = value - (nextval * 2);
    //send bit here
    value = nextval;
 }

这比尝试使用没有掩码和移位的浮点数的按位表示更好。


0
投票

位移就像乘法或除法一样,所以最简单的左/右N位移位解决方案只是乘以/除以2N

const unsigned int SHIFT_BY[] = { 1U, 2U, 4U, 8U, 16U, 32U, 64U, 128U, 256U, 512U,
    1024U, 2048U, 4096U, 8192U, 16384U, 32768U, 65536U, 131072U, 262144U, 524288U,
    1048576U, 2097152U, 4194304U, 8388608U, 16777216U, 33554432U, 67108864U,
    134217728U, 268435456U, 536870912U, 1073741824U, 2147483648U};

unsigned int lshift(unsigned int x, unsigned int numshift)
{
    return x*SHIFT_BY[numshift];
}
unsigned int rshift(unsigned int x, unsigned int numshift)
{
    return x/SHIFT_BY[numshift];
}

但是,对于小型移位步骤或没有除法/乘法的架构,这将不会有效。在这种情况下,只需将数字添加到自身,因为它相当于将它乘以2,这可能会稍微提高性能

unsigned int lshift(unsigned int x, unsigned int numshift)
{
    for (i = 0; i < numshift; i++)
        x += x;
    return x;
}

右移是a lot trickier to implement,只有加/减。如果您不想使用慢速除法,则可以使用查找表

unsigned int rshift1(unsigned int x)
{
    const unsigned int RSHIFT1[] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
    assert(x < 16);
    retrn RSHIFT1[x];
}

上面只是一个简单的4位LUT,可以移动1.如果你想要/可以使用更大的LUT。您还可以将2D的数组移位1次以上,或者多次移1次。该方法也可以应用于左移

© www.soinside.com 2019 - 2024. All rights reserved.