Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中双变量数据类型的算术位移位_C_Math_Pointers_Matrix_Shift - Fatal编程技术网

C语言中双变量数据类型的算术位移位

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][

我正在尝试对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][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;


}