请用C语言实现将double类型数据转换成字符串,再转换成double类型的数据、int类型的数据
想要完成题目中的功能,首先我们的先对系统存储double的格式有所了解。
浮点数编码转换使用的是IEEE的编码标准。
类型
|
存储位数
|
| | |
偏置值
|
|
|
数符(S)
|
阶码(E)
|
尾数(M)
|
总位数
|
十六进制
|
十进制
|
短浮点数(Single,float)
|
1位
|
8位
|
23位
|
32位
|
7FH
|
+127
|
长浮点数(Double)
|
1位
|
11位
|
52位
|
64位
|
3FFH
|
+1023
|
临时浮点数(扩展精度浮点数)
|
1位
|
15位
|
64位
|
80位
|
3FFFH
|
+16383
|
如上图可以看到double类型占8字节空间,最高位存储符号位,
然后接下来11位存储(1023+指数位),剩下的52位存储的科学计数法的位数,
整数部分默认为1,所以被省略了
下面用实例解析一下:
浮点数 -9988777.25 是负数,所以最高位为1,
然后将9988777.25转换成二进制 100110000110101010101001.01,
然后转换成科学计数就是1.0011000011010101010100101 * 2^23,那么指数就是23, 接下来11位是1023+23=1046
那么剩余的52位存储的尾数是0011000011010101010100101,不足52位在后门补0,多于52位的舍弃
完整的64位存储值应该是这样的: 1 10000010110 0011000011010101010100101 000000000000000000000000000 = 0xC1630D5528000000
下面我们按照国际惯例用vs2013建个工程,里面输入代码,在 double db = -9988777.25处打个断点,
F5调试起来,然后在内存窗口查看变量db, 可以看到如下图 0x002BFBA8 00 00 00 28 55 0d 63 c1
可以看到正好和我们推算的值0xC1630D5528000000相等。
实现代码的时候发现这个花费的时间有点长啊,感觉不对劲,再看看题目发现我跑题了,
题目中说用C语言实现,没有限定我们使用C标准库,那么我们用ecvt这个函数来获取他的符号位和指数,
简单处理一下字符串中的小数点就行了。下面上代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> //double 转换成 字符串 double to ascii char* dtoa(double Val, int NumberOfDigits, int *Dec, int *Sign) { //NumberOfDigits是精度,Dec是指数,Sign表示是否有符号 char *pdouble = ecvt(Val, NumberOfDigits, Dec, Sign); //添加小数点到字符串中 int i = 0; for (i = strlen(pdouble); i >= *Dec; i--) { pdouble[i + 1] = pdouble[i]; } pdouble[i+1] = '.'; //如果是负数添加负号到字符串前面 if (*Sign) { for (i = strlen(pdouble); i > 0; i--) { pdouble[i + 1] = pdouble[i]; } pdouble[0] = '-'; } return pdouble; } int main() { int Dec = 0, Sign = 0; char *p; double db; int idb; //double类型转换成字符串 p = dtoa(9988777.25, 10, &Dec, &Sign); //字符串转换成double db = atof(p); //字符串转换成int idb = atoi(p); printf("%s %lf %d\n",p, db, idb); return 0; }
如果有什么问题和疑问可以在下面留言互相探讨。
原题我已经上传到这里了http://download.csdn.net/detail/yincheng01/6461073 ,
解压密码为 c.itcast.cn