51Testing软件测试论坛

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

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

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

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

[复制链接]

该用户从未签到

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

使用道具 举报

该用户从未签到

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);
            }
            
}
回复 支持 反对

使用道具 举报

  • 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。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    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位二进制数的全过程了,可能有些地方写得不够清楚,望大家谅解。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

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

    32位浮点数的格式

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

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

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

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

    使用道具 举报

    本版积分规则

    关闭

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

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

    GMT+8, 2024-11-16 18:54 , Processed in 0.067133 second(s), 24 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

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