【问题标题】:Bitset to float or double value c++位设置为浮点值或双精度值 C++
【发布时间】:2018-10-03 11:58:19
【问题描述】:

我有两个浮点(32 位)和双精度(64 位)的 IEEE754 二进制表示位集。 如何将此位集转换为 REAL 浮点数或双精度数?

【问题讨论】:

    标签: c++ floating-point bitset


    【解决方案1】:

    使用bitset::to_ullong()memcpy() 位。

    【讨论】:

    • 请注意,这仅适用于使用该格式的浮点数的系统,这是不保证(可能是字节序,可能只是完全不同的格式)。如果您需要支持其他系统,则需要进行实际转换。
    • @FireLancer 我不认为你是正确的。中间的 ulong 将简单地存储 bitset 的任何内容,我们已经知道它在 IEEE754 中。
    • @BartekBanachewicz 如果代码运行的系统是not IEEE754,那么floatdoublememcpy进入的结果将不会有预期价值。
    • 对,没错。
    【解决方案2】:

    这是一个不依赖于使用 IEEE-754 类型的 C++ 实现的解决方案。

    s 成为bitset 的第一位。

    e 分别为 32 位或 64 位的下一个 8 位或 11 位。

    f 分别为剩余的 23 位或 52 位。

    Ebias 分别为 127 或 1023。

    Emax 分别为 255 或 2047。

    Fscale 分别为 0x1p-23 或 0x1p-52。

    然后此代码返回解释为 IEEE-754 基本二进制浮点对象的位集的值:

    // Interpret the sign.
    double S = s ? -1 : +1;
    
    // Classify the exponent.
    if (e == 0)
        // The value is zero or subnormal.
        return S * std::ldexp(f*Fscale, 1-Ebias);
    
    else if (e < eMax)
        // The value is normal.
        return S * std::ldexp(1 + f*Fscale, e-Ebias);
    
    else
        // The value is NaN or infinite.
        if (f == 0)
            // The value is infinite.
            return S * INFINITY;
        else
            // The value is a NaN.
            return NAN;
    

    这不会将 NAN 中的所有位(包括符号位)设置为与位集中的确切位匹配。没有便携的方法可以做到这一点。通常必须通过使用memcpy 或其他通过字符类型的复制将位复制到floatdouble 对象来完成,并且它要求C++ 实现使用floatdouble 类型即 IEEE-754。当然,以上要求C++实现支持NANINFINITY,并且C++实现中的浮点类型能够表示值。

    【讨论】:

      【解决方案3】:

      首先,一个不只是代表IEEE 754 floating point。这种表示形式有很多内容。假设您有一个bitset 变量:param,并且您想将其转换为float。为保证这是一次有效的转换,您需要确保:

      • param.size() == sizeof(float) * CHAR_BIT
      • 编码paramendianness 匹配endian::native
      • numeric_limits&lt;float&gt;::is_iec559 是真的
      • 编码param 的基数与numeric_limits&lt;float&gt;::radix 匹配

      如果所有这些都是真的,那么这些位实际上是内部浮点表示的格式,并且您可以使用这样的简单函数进行转换(前提是 sizeof(unsigned long) == sizeof(float)sizeof(unsigned long long) == sizeof(double)):

      double foo(const bitset<sizeof(double) * CHAR_BIT>& param) {
          const auto val = param.to_ullong();
          double result;
      
          memcpy(&result, &val, sizeof(double));
      
          return result;
      }
      
      float foo(const bitset<sizeof(float) * CHAR_BIT>& param) {
          const auto val = param.to_ulong();
          float result;
      
          memcpy(&result, &val, sizeof(float));
      
          return result;
      }
      

      【讨论】:

      • is_iec559 不是一个普遍有用的指标。如果类型(包括算术和其他行为)符合 IEC 60559/IEEE 754,is_iec559 应该为真。但是,许多 C++ 实现使用 IEEE-754 格式但不符合其算术要求,因此不设置 is_iec559 .所以is_iec559 不能作为是否使用 IEEE-754 格式的指标。
      • @EricPostpischil 是的......关键点是 not IEEE 754 never 的浮点设置了这个。我将通过演示如何提取位来重新制定不符合 IEEE 754 的浮点数来工作......但后来我意识到可能没有人会看到这个答案,所以几乎没有理由将它扩展到最简单的用例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 2011-11-17
      • 1970-01-01
      • 1970-01-01
      • 2022-11-19
      • 1970-01-01
      相关资源
      最近更新 更多