C语言中双变量数据类型的算术位移位
我正在尝试对C中的双数据类型进行算术位移位。我想知道这样做是否正确: 注意:firdelay[]]在main中声明为 双五层[8][12]C语言中双变量数据类型的算术位移位,c,math,pointers,matrix,shift,C,Math,Pointers,Matrix,Shift,我正在尝试对C中的双数据类型进行算术位移位。我想知道这样做是否正确: 注意:firdelay[]]在main中声明为 双五层[8][12] void function1(double firdelay[][12]) { int * shiftptr; // Cast address of element of 2D matrix (type double) to integer pointer *shiftptr = (int *) (&firdelay[0][
void function1(double firdelay[][12]) {
int * shiftptr;
// Cast address of element of 2D matrix (type double) to integer pointer
*shiftptr = (int *) (&firdelay[0][5]);
// Dereference integer pointer and shift right by 12 bits
*shiftptr >>= 12;
}
浮点数据类型(重新解释为int)的位移位会让你胡言乱语(看看二进制表示的图表,看看原因)
如果你想乘/除2的幂,那么你应该明确地这样做。没有正确的方法。按位移位浮点数据类型的两个操作数都不会给出所需的结果 在Simulink中,移位算术块仅对整数数据类型进行位移位。如果输入浮点类型,则将输入信号除以
2^N
,其中N是掩码对话框中指定的要移位的位数
编辑:由于您没有执行任何浮点运算的能力,因此您可以选择:
- 了解浮点单精度数的定义,然后了解如何按位操作它以实现除法李>
- 将要移植的任何算法转换为使用定点数据类型而不是浮点数据类型
我推荐选项2,它比1容易得多。根据措辞拙劣且非常不清楚的说法,Simulink中的“位移位”似乎采用了两个浮点值参数,并具有将浮点值乘以两个参数的效果
您可以使用
ldexp(双倍数字,位到伪移位)
来获得此行为。函数ldexp
可在中找到。一个潜在的使用案例是捕获尾数位、指数位和符号位(如果感兴趣)。为此,您可以使用联合体:
union doubleBits {
double d;
long l;
};
您可以将您的双人房设置为在联合体中设置:
union doubleBits myUnion;
myUnion.d = myDouble;
以及在提取位之后对并集的长部分进行位移位,如下所示:
myUnion.l >>= 1;
由于定义了double的每个部分的位数,因此这是提取底层位表示的一种方法。这是一个可以获得原始底层位的用例。我不熟悉Simulink,但如果这可能是双精度被移位的原因,这可能是在C中实现这种行为的一种方法。它总是12位的事实让我不这么认为,但是以防万一,我认为对于其他偶然发现这个问题的人来说,这是值得指出的。有一种方法可以实现这一点:只需将n添加到double的按位表示的指数部分。
使用“重新解释”或按位转换(例如使用并集)将双精度转换为长精度。。从52到63(11位)提取位。。然后添加移位并将结果放回指数中。
您应该考虑double(+无穷大、nan或零)的特殊值
double运算符左移(双a,整数n)
{
联合
{
长l;
双d;
}r;
r、 d=a;
开关(左)
{
案例0x0000000000000000://0
案例0x80000000000000://-0
案例0x7FF0000000000000://位置信息
案例0xFFF0000000000000://neg infnity
案例0x7FF0000000000001://Nan
案例0x7FF80000000001://Nan
案例0x7fffffffffffff://Nan
返回a;
}
int nexp=((r.l>>52)&0x7FF)+n);//新指数
if(nexp2047)//溢出
{
r、 l=(r.l&0x800000000000000)| 0x7FF00000000000000;
//返回+/-无穷大
返回r.d;
}
//返回带有新指数的数字
r、 l=(r.l&0x800FFFFFFFFFFFFF)|((长-长)nexp)你希望通过双精度位移位实现什么?我正在将simulink模型转换为C,在该模型中,双精度位使用移位运算块以12位的算术方式右移。因此,我需要在C中做同样的事情。你能指出描述模型的某个链接吗?我真的怀疑通过位移位可以得到有意义的东西g双精度。这个模型是数字-->转换成双精度-->位右移12位或使用frexp/ldexp。但是现在的编译器很聪明。我不是把数据类型转换成整数,我只是把地址转换成整数指针。根据这个网站:你就是这么做的。@starbox:写这个链接的人应该被枪毙。我在这里s不能保证float
和int
具有相同的大小,也无法保证结果应该是什么。不要对浮点数进行位移位,最重要的是,不要使用那些类型双关技巧。它们的行为是未定义的。@starbox:它只会将符号位移位到指数中,将指数位移位到t中他用尾数,扔掉一些尾数位。可能不是你想要的!@starbox通过右移,你只需将符号位移向指数位,将指数位移向分数位().所以结果没有任何意义。请看我下面的答案,了解为什么它在Simulink中工作。所以基本上你是说我应该除以2^N而不是位移位?嗯……我需要在C代码完成后将此模型转换为汇编,知道我如何将此方法扩展到汇编吗?(在我的程序集中,每个数据字是16位)是的,如果输入数据类型是浮点,则应进行除法运算。为什么需要手动将C转换为汇编?编译器将负责此操作。假设您的平台支持浮点数据,编译器将知道生成什么汇编指令来进行浮点除法。@starbox:若要转换为汇编,请让编译器执行此操作它是为您准备的(-S
开关用于gcc)。@Praetorian:我正在为一个没有为其编写编译器的处理器编写汇编代码。@Praetorian:一个具有128个指令字si的多核处理器
double operator_shift_left(double a,int n)
{
union
{
long long l;
double d;
} r;
r.d=a;
switch(r.l)
{
case 0x0000000000000000: // 0
case 0x8000000000000000: // -0
case 0x7FF0000000000000: // pos infnity
case 0xFFF0000000000000: // neg infnity
case 0x7FF0000000000001: // Nan
case 0x7FF8000000000001: // Nan
case 0x7FFFFFFFFFFFFFFF: // Nan
return a;
}
int nexp=(((r.l>>52)&0x7FF)+n); // new exponent
if (nexp<0) // underflow
{
r.l=r.l & 0x8000000000000000;
// returns +/- 0
return r.d;
}
if (nexp>2047) // overflow
{
r.l=(r.l & 0x8000000000000000)| 0x7FF0000000000000;
// returns +/- infinity
return r.d;
}
// returns the number with the new exponant
r.l=(r.l & 0x800FFFFFFFFFFFFF)|(((long long)nexp)<<52);
return r.d;
}