[英]Converting float values from big endian to little endian
Is it possible to convert float
s from big to little endian?是否可以将float
s从大端转换为小端? I have a big endian value from a PowerPC platform that I am sendING via TCP to a Windows process (little endian).我有一个来自 PowerPC 平台的大端值,我通过 TCP 发送到 Windows 进程(小端)。 This value is a float
, but when I memcpy
the value into a Win32 float type and then call _byteswap_ulong
on that value, I always get 0.0000?这个值是一个float
,但是当我将该值memcpy
转换为 Win32 浮点类型,然后对该值调用_byteswap_ulong
时,我总是得到 0.0000?
What am I doing wrong?我究竟做错了什么?
simply reverse the four bytes works只需反转四个字节即可
float ReverseFloat( const float inFloat )
{
float retVal;
char *floatToConvert = ( char* ) & inFloat;
char *returnFloat = ( char* ) & retVal;
// swap the bytes into a temporary buffer
returnFloat[0] = floatToConvert[3];
returnFloat[1] = floatToConvert[2];
returnFloat[2] = floatToConvert[1];
returnFloat[3] = floatToConvert[0];
return retVal;
}
Here is a function can reverse byte order of any type.这是一个可以反转任何类型字节顺序的函数。
template <typename T>
T bswap(T val) {
T retVal;
char *pVal = (char*) &val;
char *pRetVal = (char*)&retVal;
int size = sizeof(T);
for(int i=0; i<size; i++) {
pRetVal[size-1-i] = pVal[i];
}
return retVal;
}
I found something roughly like this a long time ago.很久以前我发现了大致类似的东西。 It was good for a laugh , but ingest at your own peril.这很好笑,但要自担风险。 I've not even compiled it:我什至没有编译它:
void * endian_swap(void * arg)
{
unsigned int n = *((int*)arg);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
*arg = n;
return arg;
}
An elegant way to do the byte exchange is to use a union:进行字节交换的一种优雅方式是使用联合:
float big2little (float f)
{
union
{
float f;
char b[4];
} src, dst;
src.f = f;
dst.b[3] = src.b[0];
dst.b[2] = src.b[1];
dst.b[1] = src.b[2];
dst.b[0] = src.b[3];
return dst.f;
}
Following jjmerelo's recommendation to write a loop, a more generic solution could be:按照 jjmerelo 编写循环的建议,更通用的解决方案可能是:
typedef float number_t;
#define NUMBER_SIZE sizeof(number_t)
number_t big2little (number_t n)
{
union
{
number_t n;
char b[NUMBER_SIZE];
} src, dst;
src.n = n;
for (size_t i=0; i<NUMBER_SIZE; i++)
dst.b[i] = src.b[NUMBER_SIZE-1 - i];
return dst.n;
}
Don't memcpy the data directly into a float type.不要将数据直接存储为浮点类型。 Keep it as char data, swap the bytes and then treat it as a float.将其保留为字符数据,交换字节,然后将其视为浮点数。
From SDL_endian.h with slight changes:从SDL_endian.h略有变化:
std::uint32_t Swap32(std::uint32_t x)
{
return static_cast<std::uint32_t>((x << 24) | ((x << 8) & 0x00FF0000) |
((x >> 8) & 0x0000FF00) | (x >> 24));
}
float SwapFloat(float x)
{
union
{
float f;
std::uint32_t ui32;
} swapper;
swapper.f = x;
swapper.ui32 = Swap32(swapper.ui32);
return swapper.f;
}
This value is a float, but when I "memcpy" the value into a win32 float type and then call
_byteswap_ulong
on that value, I always get 0.0000?这个值是一个浮点数,但是当我将这个值“memcpy”成一个 win32 浮点类型,然后对该值调用_byteswap_ulong
时,我总是得到 0.0000?
This should work.这应该有效。 Can you post the code you have?你能把你的代码贴出来吗?
However, if you care for performance (perhaps you do not, in that case you can ignore the rest), it should be possible to avoid memcpy, either by directly loading it into the target location and swapping the bytes there, or using a swap which does the swapping while copying.但是,如果您关心性能(也许您不关心,在这种情况下您可以忽略其余部分),应该可以避免 memcpy,方法是将其直接加载到目标位置并在那里交换字节,或者使用交换它在复制时进行交换。
in some case, especially on modbus: network byte order for a float is:在某些情况下,尤其是在 modbus 上:浮点数的网络字节顺序是:
nfloat[0] = float[1]
nfloat[1] = float[0]
nfloat[2] = float[3]
nfloat[3] = float[2]
A nice way to get to the value is to use struct.pack/unpack. 获得该值的一种好方法是使用struct.pack / unpack。
You can use the ">" character in the format to indicate that the bytes are in reverse (big endian). 您可以使用格式中的“>”字符来表示字节是反向的(大字节序)。
from struct import unpack, pack
sebytes = '\xc8\x00\x00\x00'
print unpack('l', sebytes)
bebytes = '\x00\x00\x00\xc8'
print unpack('>l', bebytes)
output: 输出:
(200,)
(200,)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.