代码之家  ›  专栏  ›  技术社区  ›  user2400026

将浮点数1864.78转换为二进制和IEEE格式

  •  0
  • user2400026  · 技术社区  · 8 年前

    我一直在尝试转换S&P500,今天是1864.78,它将如何在存储器中以IEEE单精度格式表示。

    转换小数点的左边(1864)很容易。

    11101001000

    但是我如何得到十进制(.78)的二进制表示呢?我尝试使用该技术,但它在8位指数IEEE格式上生成了许多数字:

    .78*2=1.56 1

    .56*2=1.12 1

    .12*2=.24 0

    .24*2=.48 0

    .48*2=.96 0

    .96*2=1.92 1

    .92*2=1.84 1

    .84*2=1.68 1

    .68*2=1.36 1

    .36*2=.72 0

    .72*2=1.44 1

    .44*2=.881(四舍五入,因为现在我们总共有23位)

    11101001000.110001111011=尾数的23位

    为签名添加0

    0 11101001000.110001111011

    现在我需要将小数移到10位

    1.110100100011001111011 x 2^10指数现在为10

    加一个0位,使尾数为23位

    1.11010010001100011110110

    指数为10,因此10+127=137

    等于10001001

    因此0 10001001 1101001000110001110110是32位数字。

    这看起来像一个体面的方法吗?我测试了它的价值,并写了这个问题,我实际上能够自己解决它。

    用这个测试十进制FP。 http://www.h-schmidt.net/FloatConverter/IEEE754.html

    2 回复  |  直到 8 年前
        1
  •  7
  •   David C. Rankin    8 年前

    您有两个不同的转换例程用于将整数和小数部分转换为二进制。你知道如何转换 1864 转换为二进制,但转换时遇到问题 .78 转换为二进制。 注: 您必须转换中的实际分数 记忆力 对于浮子 1864.78 这是 1864.780029 或分数 0.780029 0.78 。这就是你的“四舍五入”困惑的来源。

    要将分数转换为其二进制表示形式,您需要将分数乘以 2 并且如果结果数字的整数部分大于 1 ,该位的二进制表示为 1. ,如果不是,您的代表是 0 。如果大于1,则减去 1. 从数字开始重复,直到你用尽了数字或达到了所讨论的精度极限。例如:

    number   : 1864.78
    float    : 1864.780029  (actual nearest representation in memory)
    integer  : 1864
    fraction : 0.780029
    
     2 * 0.780029 = 1.560059  =>  integer part (1) fraction (0.560059)  =>  '1'
     2 * 0.560059 = 1.120117  =>  integer part (1) fraction (0.120117)  =>  '1'
     2 * 0.120117 = 0.240234  =>  integer part (0) fraction (0.240234)  =>  '0'
     2 * 0.240234 = 0.480469  =>  integer part (0) fraction (0.480469)  =>  '0'
     2 * 0.480469 = 0.960938  =>  integer part (0) fraction (0.960938)  =>  '0'
     2 * 0.960938 = 1.921875  =>  integer part (1) fraction (0.921875)  =>  '1'
     2 * 0.921875 = 1.843750  =>  integer part (1) fraction (0.843750)  =>  '1'
     2 * 0.843750 = 1.687500  =>  integer part (1) fraction (0.687500)  =>  '1'
     2 * 0.687500 = 1.375000  =>  integer part (1) fraction (0.375000)  =>  '1'
     2 * 0.375000 = 0.750000  =>  integer part (0) fraction (0.750000)  =>  '0'
     2 * 0.750000 = 1.500000  =>  integer part (1) fraction (0.500000)  =>  '1'
     2 * 0.500000 = 1.000000  =>  integer part (1) fraction (0.000000)  =>  '1'
    

    注意: 如何 浮点 分数将趋向于零,而不是达到位数的极限。如果您尝试转换 0.78 (不能精确表示为 1864.78 在32位浮点值中),您将在第12位中获得不同的转换。

    将分数部分转换为二进制后,可以继续转换为IEEE-754单精度格式。例如。:

    decimal  : 11101001000
    fraction : 110001111011
    sign bit : 0
    

    偏差指数的归一化为:

     11101001000.110001111011  =>  1.1101001000110001111011
    
         exponent bias: 10
     unbiased exponent: 127
     __________________+____
    
       biased exponent: 137
       binary exponent: 10001001
    

    转换为“隐藏位”格式以形成尾数:

    1.1101001000110001111011  =>  1101001000110001111011
    

    然后使用 符号位 + 超额127指数 + 尾数 形成IEEE-754单精度表示:

    IEEE-754 Single Precision Floating Point Representation
    
      0 1 0 0 0 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 1 0 0 0 1 1 1 1 0 1 1 0
     |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
     |s|      exp      |                  mantissa                   |
    

    仔细看看,如果你还有其他问题,请告诉我。如果你想用一个简单的例程来填充一个字符数组,你可以做如下类似的事情来将浮点小数部分转换成二进制:

    #define MANTISSA 23
    ...
    
    /** return string containing binary representation of fraction
     *  The function takes a float as an argument and computes the
     *  binary representation of the fractional part of the float,
     *  On success, the function returns a null-terminated string
     *  containing the binary value, or NULL otherwise. The conversion
     *  is limited to the length of your MANTISSA (23-bits for single
     *  precission, 52-bits for double precision). You must insure
     *  you provide a buffer for 's' of at least MANTISSA + 1 bytes.
     */
    char *fpfrc2bin (char *s, float fvalue)
    {
        /* obtain fractional value from fvalue */
        float fv = fvalue > 1.0 ? fvalue - (int)fvalue : fvalue;
        char *p = s;
        unsigned char it = 0;
    
        while (fv > 0 && it < MANTISSA + 1)
        {   /* convert fraction */
            fv = fv * 2.0;
            *p++ = ((int)fv) ? '1' : '0';
            *p = 0;  /* nul-terminate */
            fv = ((int)fv >= 1) ? fv - 1.0 : fv;
            it++;
        }
    
        return s;
    }
    
        2
  •  1
  •   Simon Byrne    8 年前

    你太短了1位:IEEE754二进制32格式使用24位有效位,但使用23位和隐式前导1存储。

    因此,最后2位是:

    0.44*2=0.88 0           => 1
    0.88*2=1.76 2 (rounded) => 0 (carry the extra bit)
    

    它给出了数字

    1.11010010001100011110110 2. × 2 10

    您已经计算了偏差指数(137=10001001 2. ),因此可以直接构造得到的比特模式:

    0 10001001 11010010001100011110110