51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1837|回复: 4
打印 上一主题 下一主题

如何把十进制实数转换成32位二进制数

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2008-1-9 16:43:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
记得在学校上过一门课叫《计算机组成原理》,其中有一小节内容是关于浮点数的,什么又是尾数又是阶码还有对阶等等,当时听的我是云里雾里的,反正就是没怎么听懂,觉得这个东西在以后的工作中不会碰到,所以也就没有最后也没有好好学习,不懂就不懂了吧。
    毕业了,工作了,进入一家自动化控制公司工作,期间会用到各种PLC,并用LD和FBD语言编写控制程序。幸好,在实际的编程中还不需要用到浮点运算,而且大部分的PLC也没有浮点处理器,万幸啊。不过有一次我在看一种PLC的技术资料时,发现里面提到了浮点运算,因为当时工作中没有这个需要,自己也就草草地一眼带过了。
    不幸的事还是发生了,自己在工作之余学习用汇编编写OpenGL的时候,发现需要用到大量的浮点运算,这下完了,这条沟我过不去了。没办法,只能再翻书,再找资料学习关于浮点数的知识。
    下面我就把我学到的东西写出来,给大家伙看看,如果谁在工作中会遇到这样的问题也能有所帮助。
    注:这里我只写32位的浮点数,64位其实是一样的。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

该用户从未签到

2#
 楼主| 发表于 2008-1-9 16:51:17 | 只看该作者

32位浮点数的格式

32位浮点数由三部分组成
一.符号位
二.阶码
三.尾数

〖符号位〗位于最高位的第31位,其占用32位里的1位,该位值为〖0〗表示整个浮点数为正数,该位值为〖1〗表示整个浮点数为负数

〖阶码〗位于第23位~第30位,其占用32位里的8位

〖尾数〗位于第0位~第22位,其占用32位里的23位
回复 支持 反对

使用道具 举报

该用户从未签到

3#
 楼主| 发表于 2008-1-9 17:40:44 | 只看该作者

开始转换,并用例子加以说明

现在把十进制实数13.437转换32位二进制
一.把13转换成二进制,结果为1101
二.把0.437转换成二进制,结果为0.0110;1111;1101;1111;0011;101
      这个结果只是近似值,还可以继续计算下去,但在这里已经不需要了
   这里用〖;〗把数字分开只是为了方便数位数,下面也是如此
三.把两个结果相加,结果为1101.0110;1111;1101;1111;0011;101
四.计算尾数,把小数点移到最高一位〖1〗的右面
  (为什么要移?没有为什么,要移就是要移)
   结果为1.1010;1101;1111;1011;1110;0111;01
      小数点向左移动了3位,记住这个值,在后面阶码运算的时候要用到
      这个过程叫什么?我忘了 好象是〖对阶〗也好象是〖规格化〗
五.计算阶码。用刚才移动的位数(向左移动为正数,向右移动为负数)+3,加上127
     结果为130
     为什么要加127,我也不知道,希望看到这的并且知道原因的兄弟姐妹能够告诉小弟一声
六.把计算出的阶码〖130〗转换成二进制,结果为1000;0010
     好了,做到现在一切准备工作都完成了,接下来就是根据浮点数的格式把这些值写
   成32位二进制数了
七.填写〖符号位〗,其值为〖0〗,共1位
   填写〖阶码〗,其值为〖1000;0010〗,共8位
   填写〖尾数〗,其值为〖1010;1101;1111;1011;1110;011〗,共23位
   填写〖尾数〗时,小数点左边的〖1〗不需要
八.组合上面的结果,最后的结果就是
  〖0100;0001;0101;0110;1111;1101;1111;0011〗,共32位
   十进制结果为〖65;86;253;243〗
   十六进制结果为〖41;56;FD;F3〗

终于转换好了,累啊,结果对不对呢?用VC来检查一下。
结果怎么样?好象不对,为什么VC里面的值是〖41;56;FD;F4〗,比我们手工计算的
大1?我们计算错了?其实不是,只不过我们最后还没有进行〖舍入〗处理。〖舍入〗的原则就是〖0舍1入〗
九.舍入处理
   在第四步中为数的结果是1.1010;1101;1111;1011;1110;0111;01
   在第八步中,组合整个数值的时候,把最后3位〖101〗给去除了
   这时的舍入就要根据这个被去除的数值的最高一位来处理,如果最高一位是〖1〗,最后
   的结果要加上1,如果最高一位是〖0〗,最后的结果不变。这就是〖0舍1入〗
   所以在VC中看到的结果会比我们手动计算的大1。好了,最后舍入处理结束后,最后正
   确的结果就是〖0100;0001;0101;0110;1111;1101;1111;0100〗

以上就是十进制实数转换成32位二进制数的全过程了,可能有些地方写得不够清楚,望大家谅解。
回复 支持 反对

使用道具 举报

  • TA的每日心情
    慵懒
    2020-8-11 08:18
  • 签到天数: 114 天

    连续签到: 1 天

    [LV.6]测试旅长

    4#
    发表于 2008-1-9 20:53:15 | 只看该作者
    。。。。。。。。
    过程我是看懂了
    但是其实大部分都没懂-_-

    唔。。。那么我说下懂的东西

    先说明下啥叫浮点数
    所谓的浮点数就是指小数点在逻辑上是不固定的
    与此相对的是定点数
    浮点数里的整数是特殊情况,小数点在最后
    (IEEE有个浮点标准,有兴趣可以去查下,这种东西我是背不出的

    然后贴一段小数转二进制的问题,估计好多人不是很明白,至少我读书那会儿,学校里是从来不讲解小数如何表示的问题的。
    具体的公式不一定要去记,但是要知道大概的过程是咋回事,事实上在我的开发经验中,类似的bug在设计中还是比较常见的,甚至有些人做到了高级技术人员对这个问题还是一无所知。

    下面我仅以float(带符号,单精度,32位)类型的浮点数说明C++中的浮点数是如何在内存中表示的。先讲一下基础知识,纯小数的二进制表示。(纯小数就是没有整数部分的小数,讲给小学没好好学的人)
    纯小数要想用二进制表示,必须先进行规格化,即化为 1.xxxxx * ( 2 ^ n ) 的形式(“^”代表乘方,2 ^ n表示2的n次方)。对于一个纯小数D,求n的公式如下:
    n = 1 + log2(D);// 纯小数求得的n必为负数
    再用 D / ( 2 ^ n ) 就可以得到规格化后的小数了。接下来就是十进制到二进制的转化问题,为了更好的理解,先来看一下10进制的纯小数是怎么表示的,假设有纯小数D,它小数点后的每一位数字按顺序形成一个集合:
    {k1, k2, k3, ... , kn}
    那么D又可以这样表示:
    D = k1 / (10 ^ 1 ) + k2 / (10 ^ 2 ) + k3 / (10 ^ 3 ) + ... + kn / (10 ^ n )
    推广到二进制中,纯小数的表示法即为:
    D = b1 / (2 ^ 1 ) + b2 / (2 ^ 2 ) + b3 / (2 ^ 3 ) + ... + bn / (2 ^ n )
    现在问题就是怎样求得b1, b2, b3,……,bn。算法描述起来比较复杂,还是用数字来说话吧。声明一下,1 / ( 2 ^ n )这个数比较特殊,我称之为位阶值。
    例如0.456,第1位,0.456小于位阶值0.5故为0;第2位,0.456大于位阶值0.25,该位为1,并将0.45减去0.25得0.206进下一位;第3位,0.206大于位阶值0.125,该位为1,并将0.206减去0.125得0.081进下一位;第4位,0.081大于0.0625,为1,并将0.081减去0.0625得0.0185进下一位;第5位0.0185小于0.03125……
    最后把计算得到的足够多的1和0按位顺序组合起来,就得到了一个比较精确的用二进制表示的纯小数了,同时精度问题也就由此产生,许多数都是无法在有限的n内完全精确的表示出来的,我们只能利用更大的n值来更精确的表示这个数,这就是为什么在许多领域,程序员都更喜欢用double而不是float。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    5#
    发表于 2008-6-1 19:27:44 | 只看该作者
    我只会 整形的转换,c代码如下

    #include "stdio.h"
    #include "math.h"
    main()
    {
            void binary(int num);
        int num;
        printf("please enter a number:\n");
        scanf("%d",&num);
        printf("the binary of num is:\n");
        binary(num);
        printf("\n");

    }
    void binary(int num)
    {
            int surplus,i=0,j,n,a[32];
            n=fabs(num);
            /*二进制算法:整数(正数)除以2其余数从末尾往前补*/
            while(n>=2)
            {
                    surplus=n%2;
                    n/=2;
                    a=surplus;
                    i++;
            }
            a=n;
            /*余下的位置补0*/
            for(j=i+1;j<32;j++)
               a[j]=0;
            /*输出二进制表示,正数则倒序输出,负数则取反*/
            if(num>0)
              for(i=31;i>=0;i--)
                printf("%d",a);
            if(num<0)
              for(i=31;i>=0;i--)
                {
                        a=fabs(a-1);
                    printf("%d",a);
                }
                
    }
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-16 21:57 , Processed in 0.066800 second(s), 24 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表