浮点数传输与保存的方法
浮点数在软件设计中是一种非常常用的数据类型,但是浮点数的传输是一个麻烦的事情,本文旨在介绍一种浮点数的存储和传输的方式
- 本文约定浮点数在内存中存储使用的是4个字节的形式和int类型一致,注意不同操作系统可能不相同
1、方案说明
话不多说直接上代码
#include <stdio.h>
int main()
{
float a=1.2,b=0;
unsigned int c=0,d=0;
unsigned char buf[4]={0};
/* 发送方 */
c=*(unsigned int *)(&a);
buf[0]=c>>24;
buf[1]=c>>16;
buf[2]=c>>8;
buf[3]=c>>0;
/* 接受方 */
d=(((unsigned int)buf[0])<<24 | ((unsigned int)buf[1])<<16 |
((unsigned int)buf[2])<<8 | ((unsigned int)buf[3])<<0);
b=*(float *)(&d);
printf("a=%f a_int=%d c=%d b=%f",a,a,c,b);
return 0;
}
方案描述:
- 发送方:首先将float浮点数转化为unsigned int无符号整数读取,之后将unsigned int无符号整数拆分为四个字节的unsigned char无符号字符型数据,之后便可以拿着这四个字节的数据进行存储和传输了
- 接受方:接受到四个字符型的数据或者读取到这四个字符型数据之后,按照对应的大小端顺序组合成unsigned int无符号整数,之后再把unsigned int无符号整数转化为float浮点数读取使用
2、方案验证
使用以下代码将一个任意的浮点数转化得到四个无符号字符型数据
#include <stdio.h>
int main()
{
float a=2.67809,b=0;
unsigned int c=0,d=0;
unsigned char buf[4]={0};
c=*(unsigned int *)(&a);
buf[0]=c>>24;
buf[1]=c>>16;
buf[2]=c>>8;
buf[3]=c>>0;
d=((unsigned int)buf[0])<<24 | ((unsigned int)buf[1])<<16 |
((unsigned int)buf[2])<<8 | ((unsigned int)buf[3])<<0;
b=*(float *)(&d);
printf("a=%f a_int=%x\n c=%x b=%f\n",a,a,c,b);
printf("buf[0]=%x buf[1]=%x buf[2]=%x buf[3]=%x\n",buf[0],buf[1],buf[2],buf[3]);
return 0;
}
运行结果
a=2.678090 a_int=402b65d4
c=402b65d4 b=2.678090
buf[0]=40 buf[1]=2b buf[2]=65 buf[3]=d4
得到的四个字符存储在buf数组中,之后再编写以下接受程序将字符型型数据转化为浮点数
#include <stdio.h>
int main()
{
float b=0;
unsigned int d=0;
unsigned char buf[4]={0x40,0x2b,0x65,0xd4};
d=(((unsigned int)buf[0])<<24 | ((unsigned int)buf[1])<<16 |
((unsigned int)buf[2])<<8 | ((unsigned int)buf[3])<<0);
b=*(float *)(&d);
printf("d=%d b=%f",d,b);
return 0;
}
运行结果
d=1076585940 b=2.678090
运行结果显示得到的浮点数是正常的,验证此方法成功可用!
3、踩过的坑
在将字符型数据组合成整数的时候出现了一个离奇的现象,|
、<<
和+
之间的不可描述的关系,见代码
#include <stdio.h>
int main()
{
float b=0;
unsigned int d=0;
unsigned char buf[4]={0x40,0x2b,0x65,0xd4};
d=(((unsigned int)buf[0])<<24 + ((unsigned int)buf[1])<<16 +
((unsigned int)buf[2])<<8 + ((unsigned int)buf[3])<<0);
b=*(float *)(&d);
printf("d=%d b=%f",d,b);
return 0;
}
运行结果为
d=0 b=0.000000
d的结果为0!很离奇,移位操作结果出现了问题,更换一种方法先把移位的值保存起来再移位试一下
#include <stdio.h>
int main()
{
float b=0;
unsigned int d=0;
unsigned char buf[4]={0x40,0x2b,0x65,0xd4};
unsigned int x[4]={0};
x[0]=((unsigned int)buf[0])<<24;
x[1]=((unsigned int)buf[1])<<16;
x[2]=((unsigned int)buf[2])<<8;
x[3]=((unsigned int)buf[3])<<0;
d=((((unsigned int)buf[0])<<24) + (((unsigned int)buf[1])<<16) +
(((unsigned int)buf[2])<<8) + (((unsigned int)buf[3])<<0));
// d=x[0]+x[1]+x[2]+x[3];
b=*(float *)(&d);
printf("d=%d b=%f",d,b);
return 0;
}
运行结果
d=1076585940 b=2.678090
这样是可以的,这就奇怪了,之后把+
换成|
测试
#include <stdio.h>
int main()
{
float b=0;
unsigned int d=0;
unsigned char buf[4]={0x40,0x2b,0x65,0xd4};
d=(((unsigned int)buf[0])<<24 | ((unsigned int)buf[1])<<16 |
((unsigned int)buf[2])<<8 | ((unsigned int)buf[3])<<0);
b=*(float *)(&d);
printf("d=%d b=%f",d,b);
return 0;
}
运行结果为
d=1076585940 b=2.678090
把+
换成|
测试是可以的,后来仔细查找原因才发现|
、<<
和+
之间的不可描述的关系
猝死在运算符的优先级!
下次长记性了,没事多加个()
~