我可以访问一个在其上运行C风格脚本语言的工具。它可以声明和使用char
,int
和double
但不是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
的位数)并将输出标志设置为其值但这不能完成有点移位,因为我没有它。
答案 0 :(得分:1)
移动一个值相当于乘以/除以2(使用整数数学):
a / 2 equivalent to a >> 1
a * 2 equivalent to a << 1
您需要检查脚本语言是否进行整数数学运算(或使用floor()
或int()
或trunc()
或使用语言提供的语言。
请注意溢出,如果脚本语言使用float而不是int来表示数字,那么您可能会发现大数字的奇怪行为。
关于签名的另一个警告。如果你必须处理负数,那么向左移动会更复杂。
你可以运行几个测试来检查整数的大小吗?它肯定会帮助你避免问题。
答案 1 :(得分:0)
左移1等于乘2,右移1等于(整数)除以2.因此,左移3等于乘8(因为它是2 3 )。
#include <stdio.h>
int main() {
int a = 17 << 4;
int b = 17 * 16;
if (a == b) {
printf("%i\n", b);
} else {
puts("false");
}
}
输出
272
答案 2 :(得分:0)
假设您尝试检索的测量值确实是双倍的:如果您知道测量的允许范围,我会将它们乘以系数0xFFFFFFFF/MAX_RANGE
因子,以得到0到最大值之间的值。
然后你可以做
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;
}
这比尝试使用没有掩码和移位的浮点数的按位表示更好。
答案 3 :(得分:0)
位移就像乘法或除法一样,所以最简单的左/右 N位的解决方案只是乘法/除以2 N 强>
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。您还可以将移位超过1 作为2D数组,或者多次移位1。此方法也可以应用于左移