这是根据 IEEE-754 标准均衡两个不同数字的指数的正确方法吗?

Posted

技术标签:

【中文标题】这是根据 IEEE-754 标准均衡两个不同数字的指数的正确方法吗?【英文标题】:Is this the correct way of equalising exponents of two different numbers according to the IEEE-754 standard? 【发布时间】:2020-06-21 17:46:47 【问题描述】:

我省略了尾数和符号位以及处理次法线、无穷大、NaN、-0.0。我只想先关注指数,然后再关注其余部分。

    #include <stdio.h>
    
    #define N 23
    
    int binary(int n);
    int exp_diff(int exp1, int exp2);

32位结构,1位符号,8位指数,23位尾数

    union
        
        unsigned int result;
    
        struct 
            unsigned int mantissa: 23;
            unsigned int exponent: 8;
            unsigned int sign: 1;
        value;
    fps;
    
    
    int main(void)
    
        int num1 = 3;
        int num2 = 5;
        int exp1 = 0;
        int exp2 = 0;
        
        exp1 = binary(num1);
        exp2 = binary(num2);
         
        fps.value.exponent = 127 + exp_diff(exp1,exp2);
         
         printf("%08x\n", fps.result);
         
         return 0;
    
    

将值转换为二进制并返回指数

    int binary(int n)
       
        int i = 0;
        int remainder = 0;
        int a[N] = 0;
        
        while(n > 0)
            a[i++] = n % 2;
            n /= 2;
        
        return i - 1;
    
    

通过判断 epx1 是否小于 exp2 来均衡指数,反之亦然

    int exp_diff(int exp1, int exp2)
    
         if(exp1 < exp2)
            return exp2 - exp1;
         else if(exp2 < exp1)
            return exp1 - exp2;
        
    

【问题讨论】:

N 重命名为MANTISSA_NBITS 之类的名称,然后在实际位域中使用它会不会更清楚一些? 您的exp_diff 需要在底部添加一个return 0。或者,只需消除 else if 并执行:if (exp1 &lt; exp2) return exp2 - exp1; else return exp1 - exp2; binary() 中,我不太明白a[N] 数组的用途;该值已设置,但从未使用过,因此您真正需要的可能只是i++。您是否使用最大编译器警告编译了代码(这可能也会指出@CraigEstey 指出的项目)。 【参考方案1】:

使用位域访问浮点表示的内部域是有问题的,因为 C 标准在位域的布局方面为实现留下了很大的灵活性。更好的方法是使用位移和屏蔽操作。假设 float 是 32 位并且包含 &lt;stdint.h&gt;

typedef struct  unsigned sign, exponent, significand;  FloatFields;

FloatFields DecodeFloat(float x)

    uint32_t u;
    memcpy(&u, &x, sizeof u);
    return (FloatFields) 
        u >> 31,
        u >> 23 & 0xff,
        u       & 0x7fffff,
    ;


float EncodeFloat(FloatFields Fields)

    uint32_t u = Fields.sign << 31 | Fields.exponent << 23 | Fields.significand;
    float f;
    memcpy(&f, &u, sizeof f);
    return f;

关于代码fps.value.exponent = 127 + exp_diff(exp1,exp2);,不清楚它是否有任何用处。它为指数提供编码,其表示(未编码)值是操作数指数之间的绝对差异。例如,如果操作数是 1.5•27 和 1.1259,它提供了指数 2 的编码。那有什么用?也许您正试图腾出空间来定位操作数的有效数字,并在它们之间进行所需的移位,但尚不清楚您将如何使用它。根据现有的信息,总的来说,我想说这不是“使指数相等”的正确方法。

【讨论】:

以上是关于这是根据 IEEE-754 标准均衡两个不同数字的指数的正确方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

IEEE754是啥

IEEE-754 蟒蛇

计算机中的浮点数(IEEE754)

IEEE754表示格式是啥?

IEEE-754浮点标准简介

ieee754单精度浮点数 表示方法