【问题标题】:Multiplying single precision float with 2将单精度浮点数乘以 2
【发布时间】:2014-09-19 16:12:48
【问题描述】:

这是一道作业题。我已经在网上找到了很多代码,包括 StackOverflow 中的一些代码。但我只想要概念而不是代码。我想自己实现它。所以我要实现的功能是:

  • float_twice - 为浮点参数 f 返回表达式 2*f 的位级等效项。
  • 参数和结果都作为unsigned int 传递,但它们将被解释为单精度浮点值的位级表示。

我想知道如何做到这一点。我知道浮点表示。并阅读关于如何将两个浮点数相乘的wiki页面,但不明白。我只是想知道它的概念/算法。

编辑:

谢谢大家。根据您的建议,我编写了以下代码:

unsigned float_twice(unsigned uf) {
    int s = (uf >> 31) << 31;
    int e = ((uf >> 23) & 0xFF) << 23;
    int f = uf & 0x7FFF;

    // if exponent is all 1's then its a special value NaN/infinity
    if (e == 0xFF000000){
        return uf;
        
    } else if (e > 0){  //if exponent is bigger than zero(not all zeros', not al 1's, 
                        // then its in normal form, add a number to the exponent
        return uf + (1 << 23);
        
    } else { // if not exponent not all 1's and not bigger than zero, then its all 
             // 0's, meaning denormalized form, and we have to add one to fraction

        return uf +1;
    } //end of if
    
} //end of function

【问题讨论】:

  • 浮点数的一个分量代表二的幂。这是您应该感兴趣的部分。
  • 如果您知道表示的工作原理,请尝试一些示例f 并将其编码与2*f 的编码进行比较。任意浮点数的乘法比仅仅乘以 2 复杂得多,所以如果您现在无法理解前者可能并不重要。
  • 一个好的开始可能是printf()f2 * f 的位模式。
  • 数字的指数部分是2的幂;乘以 2 意味着将该值加一,担心溢出变成无穷大,NaN 保持 NaN,零保持零。
  • 请注意,您需要特殊情况的非规范化。

标签: c floating-point bit-manipulation


【解决方案1】:

你可以这样做(尽管有些人会声称它违反了严格的别名规则):

unsigned int func(unsigned int n)
{
    float x = *(float*)&n;
    x *= 2;
    return *(unsigned int*)&x;
}

void test(float x)
{
    unsigned int n = *(unsigned int*)&x;
    printf("%08X\n",func(n));
}

在任何情况下,您都必须断言float 的大小等于您平台上int 的大小。


如果您只想获取 unsigned int 操作数并对其执行将 float 乘以 2 的等效操作,那么您可以简单地将 1 添加到它的指数部分(位于位 20-30) :

unsigned int func(unsigned int n)
{
    return n+(1<<20);
}

【讨论】:

  • 我认为 OP 想要位级操作。他只需要移动代表 exp 的位。
  • @mafso:哦,好的,那我就删了。
  • 就这样吧。它向 OP 展示了如何打印一些数字的位模式,以了解从哪里开始作为 mafso,我向他提出了建议。
  • 但我会将int 更改为uint32_t 并将%u 更改为%08X
  • @Hynek-Pichi-Vychodil:嗯……对于我回答的第一部分来说,union 实际上是一个好主意。出于某种原因,我一直“忘记”该选项(可能是因为我几乎从未使用过它)。无论如何,我认为 OP 真正想要的是答案的第二部分,其中并不真正需要 union(除非您想验证操作的正确性)。
猜你喜欢
  • 2016-06-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
  • 2020-02-03
  • 1970-01-01
  • 1970-01-01
  • 2018-02-23
  • 1970-01-01
相关资源
最近更新 更多