Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5579916
  • 博文数量: 1310
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 15651
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1310)

文章存档

2020年(94)

2019年(193)

2018年(81)

2017年(80)

2016年(70)

2015年(52)

2014年(41)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: Android平台

2017-09-14 18:48:42

https://zhidao.baidu.com/question/308081047.html


  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdint.h>

  5. /*
  6. * 浮点的存储原则:
  7.     0. 浮点的正负值为 S, 占用 1Bit. 1:代表负值
  8.     1. 把浮点数的实部虚部转化为二进制, 小数点后面代表的虚部以 1/2, 1/4, 1/8, 1/16,1/32等规则叠加出来.
  9.     2. 左右移动小数点, 找出第一个 bit = 1的有效位, 得出指数部分E, 如果是左移小数点则指数+127, 占用 8Bit.
  10.     3. 除却第一个bit=1的有效位, 其他部分算作底数值M. 占用 23 bit
  11.     存储格式. 4Byte. (注意: 在小端序平台下,内存字节排列为 Byte0/1/2/3)
  12.     Byte3         Byte2        Byte1        Byte0
  13.     Address+0 Address+1 Address+2 Address+3
  14.     SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM    
  15. */

  16. void print_bin(unsigned char ch)
  17. {
  18.     int i;
  19.     printf("\n[%04d]\t", ch);
  20.     for (i=7; i>=0; i--)
  21.         printf("%d", (ch & (1<<i)) != 0);
  22.     printf("\n");

  23. }
  24. /*
  25. * 输入 pv 为小端序
  26. */
  27. void convert_float(unsigned char *p_f)
  28. {
  29.     unsigned char pv[4];
  30.     unsigned char s, e;
  31.     uint64_t M;
  32.     unsigned char *m= (unsigned char *)&M;

  33.     pv[0] = p_f[3];
  34.     pv[1] = p_f[2];
  35.     pv[2] = p_f[1];
  36.     pv[3] = p_f[0];
  37.     
  38.     s = (pv[0] & 0x80) >> 7;    
  39.     e = ((pv[0] & 0x7F) << 1) + (pv[1] >> 7) ;
  40.     //在内存中以小端序计数
  41.     m[7] = 0;
  42.     m[6] = 0;
  43.     m[5] = 0;
  44.     m[4] = 0;
  45.     m[3] = 0x01; // 1 代表有效位, 此时小数点在 m[3] 和 m[2] 之间
  46.     m[2] = ((pv[1] & 0x7F) << 1) + (pv[2] >> 7) ;
  47.     m[1] = ((pv[2] & 0x7F) << 1) + (pv[3] >> 7) ;
  48.     m[0] = ((pv[3] & 0x7F) << 1);
  49. #if 1
  50.     printf("------ SEM -----------\n");
  51.     print_bin(s); //符号 1bit
  52.     print_bin(e); //指数 8bit
  53.     //此时 M 代表的值为 1. m[2]的8bit m[1]的8bit m[0]的8bit.
  54.     print_bin(m[2]);
  55.     print_bin(m[1]);
  56.     print_bin(m[0]); //底数 23bit
  57. #endif

  58.     //得出实部/虚部
  59.     uint64_t real=0, virt=0;    

  60.     if (e < 127) { ////指数 为 负数(<127), 则 M 的小数点为左移,即代表实数部分变小, 实数为右移.
  61.         M = (M) >> (127-e);
  62.     }
  63.     else {
  64.         M = (M) << (e - 127);
  65.     }

  66. #if 1
  67.     printf("------ Real/Virt -----------\n");
  68.     print_bin(m[0]);
  69.     print_bin(m[1]);
  70.     print_bin(m[2]);
  71.     print_bin(m[3]);
  72.     print_bin(m[4]);

  73.     print_bin(m[5]);
  74.     print_bin(m[6]);
  75.     print_bin(m[7]);
  76. #endif

  77.     int i;    
  78.     // m[0] - m[4] 代表实部
  79.     for (i=7; i>=3; i--)
  80.         real = (real << 8) + m[i];        

  81.     // m[0/1/2]为虚部, 共 24Bit, 第一个 1 代表 0.5, 第二个 1 代表 0.25 ..., 即也是一个2倍差序列.
  82.     // 换成整数,仅需要把最有一个有效 1代表的数值取出, 然后乘以 虚部 的值即可.
  83.     //for (i=23; i>=0; i--) {
  84.     for (i=12; i>=0; i--) { //只保留10位精度
  85.         if (m[2-i/8] & (1<<(7-(i%8)))) break;
  86.     }
  87.     i=i+1;//i = 有效位位置
  88.     //有多少个代表值
  89.     virt = (((m[2] << 8) + m[1]) << 8) + m[0]; //2 倍差序列.
  90.     virt = virt >> (24 - i);

  91.     printf("------ Virt [%ld][%d] -----------\n", virt, i);

  92.     int j, tmp;
  93.     //先获取最后一个1的代表值.
  94.     tmp = 1;
  95.     for (j=0; j<i; j++) {
  96.         tmp = tmp * 5;
  97.     }
  98.     virt = virt * tmp;

  99.     if (s == 1)
  100.         printf("-%ld.%0*ld\n", real, i, virt);
  101.     else
  102.         printf("%ld.%0*ld\n", real, i, virt);
  103. }


  104. int main(int argc, char **argv)
  105. {
  106.     float val = 17.8;
  107.     val = atof(argv[1]);
  108.     printf("val=%f. \n", val);

  109.     unsigned char *pv = (unsigned char *)&val;
  110.     convert_float(pv);


  111. }


阅读(1258) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~