如何将长度为4的浮点数转换为字节数组(char*数组)?我需要通过网络发送一些数据,使用tcp协议,并且需要将浮点数作为字节数组发送。(我知道精度到小数点后两位,所以目前在客户端上乘以100,在服务器上除以100 - 基本上转换为整数,然后用 & 0xff 和 << 操作找到字节)。但这很丑陋,而且可能会在时间上失去精度。
如何将长度为4的浮点数转换为字节数组(char*数组)?我需要通过网络发送一些数据,使用tcp协议,并且需要将浮点数作为字节数组发送。(我知道精度到小数点后两位,所以目前在客户端上乘以100,在服务器上除以100 - 基本上转换为整数,然后用 & 0xff 和 << 操作找到字节)。但这很丑陋,而且可能会在时间上失去精度。
将任何类型作为字节序列阅读非常简单:
float f = 0.5f;
unsigned char const * p = reinterpret_cast<unsigned char const *>(&f);
for (std::size_t i = 0; i != sizeof(float); ++i)
{
std::printf("The byte #%zu is 0x%02X\n", i, p[i]);
}
从网络流写入到浮点数的操作与之类似,只需省略const
即可。
任何对象都可以被重新解释为字节序列(任何char
类型均可),这不会违反别名规则。注意,任何类型的二进制表示当然是与平台相关的,因此如果接收方平台不同,你应该仅在进行序列化时使用它。
write(fd, p, sizeof(float))
...问题是谁能读取它 :-) - Kerrek SBwrite
是正确的。但问题是要在网络上输出。因此,他所写的必须符合他使用的协议定义的格式。 - James Kanzestd::ostream&
output32BitUInt( std::ostream& dest, uint32_t value )
{
dest.put( (value >> 24) & 0xFF );
dest.put( (value >> 16) & 0xFF );
dest.put( (value >> 8) & 0xFF );
dest.put( (value ) & 0xFF );
}
对于大端字节序(通常是网络字节序),使用:
std::ostream&
output32BitUInt( std::ostream& dest, uint32_t value )
{
dest.put( (value ) & 0xFF );
dest.put( (value >> 8) & 0xFF );
dest.put( (value >> 16) & 0xFF );
dest.put( (value >> 24) & 0xFF );
}
针对一些协议使用小端模式。具体用哪种模式取决于协议定义的格式。
要将float
转换为uint32_t
,您需要检查您的编译器。在标准中,只有使用memcpy
方法能够完全保证;使用reinterpret_cast<uint32_t&>
将float强制转换为uint32_t也是可行的,大多数(或者全部?)编译器也支持使用union
。
如果需要在大型机上跨平台或者格式不是IEEE,则需要从浮点数中提取指数、符号和尾数,并以目标格式输出。以下代码可以在任何机器上(包括不使用IEEE的大型机)输出IEEE大端格式并作为参考:
oxdrstream&
oxdrstream::operator<<(
float source )
{
BytePutter dest( *this ) ;
bool isNeg = source < 0 ;
if ( isNeg ) {
source = - source ;
}
int exp ;
if ( source == 0.0 ) {
exp = 0 ;
} else {
source = ldexp( frexp( source, &exp ), 24 ) ;
exp += 126 ;
}
uint32_t mant = source ;
dest.put( (isNeg ? 0x80 : 0x00) | exp >> 1 ) ;
dest.put( ((exp << 7) & 0x80) | ((mant >> 16) & 0x7F) ) ;
dest.put( mant >> 8 ) ;
dest.put( mant ) ;
return *this ;
}
(BytePutter
是一个简单的类,它处理通常的样板并进行错误检查。) 当然,如果输出格式不是 IEEE,输出的各种操作将是不同的,但这应该展示了基本原则。(如果你需要在一些不支持 uint32_t
的异端主机上进行移植性,可以用任何大于 23 位的无符号整数类型来替换它.)
union dataUnion {
float f;
char fBuff[sizeof(float)];
}
// to use:
dataUnion myUnion;
//
myUnion.f = 3.24;
for(int i=0;i<sizeof(float);i++)
fputc(myUnion.fbuff[i],fp); // or what ever stream output....
double
。在大多数现代系统上,float
是4字节的IEEE-754格式。 - user529758