简体   繁体   English

将浮点值从大端转换为小端

[英]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.将其保留为字符数据,交换字节,然后将其视为浮点数。

It might be easier to use the ntoa and related functions to convert from network to host and from host to network..the advantage it would be portable.使用 ntoa 和相关功能从网络到主机以及从主机到网络的转换可能更容易......它的优点是可移植。 Here is a link to an article that explains how to do this. 是一篇解释如何执行此操作的文章的链接。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM