如何在Objective C中将四字节数组转换为浮点数? [英] How to convert four byte array to float in Objective C?

查看:61
本文介绍了如何在Objective C中将四字节数组转换为浮点数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有四字节数组,我喜欢在 Objective C 中转换为浮点数.我尝试了三种方法,但不确定哪种方法是正确的.

I have four byte array and I like to convert to float in Objective C. I tried three approaches and not sure what is the right approach.

我尝试的是

        unsigned char *bytearray = (unsigned char *)calloc(4, sizeof(unsigned char));
        bytearray[0] = GolfResult[i]; bytearray[1] = GolfResult[i+1]; bytearray[2] = GolfResult[i+2]; bytearray[3] = GolfResult[i+3];

    Method 1

        float result = [[NSNumber numberWithUnsignedChar:*bytearray] floatValue];

    Method 2

        float result = (float)((bytearray[3] << 24) | (bytearray[2] << 16) | (bytearray[1] << 8) | bytearray[0]);

    Method 3
        float result = (float)((bytearray[0] << 24) | (bytearray[1] << 16) | (bytearray[2] << 8) | bytearray[3]);

正确的方法是什么?

推荐答案

不幸的是,您的方法都不是正确的,因为它们都以某种方式将字节解释为整数,然后尝试将该整数转换为浮点数.这永远不会给出正确的答案,因为整数值的字节,比如 42(0x2A 位模式),与等效浮点值的字节非常不同,比如 42.0(0x42280000 位模式,作为 int 加载并转换为浮点数产生 1109917696.0).

Unfortunately none of your methods are correct as they all interpret the bytes as an integer in some way and then attempt to convert that integer to a float. This will never give the correct answer as bytes for an integer value, say 42 (0x2A bit pattern), are very different than the bytes for the equivalent floating-point value, say 42.0 (0x42280000 bit pattern which loaded as an int and converted to float produces 1109917696.0).

需要将字节直接解释为浮点格式.

What is required is to interpret the bytes directly as being in floating-point format.

您必须处理的下一个问题是存储在您的 golfResult (1) 数组中的字节的顺序.根据来源,这些字节的第一个 (golfResult[i]) 可能是最不重要的 (little endian) 或最重要的 (big endian)字节.如果您以错误的顺序组合 4 个字节,那么您得到的浮点值将不正确(2).

The next issue you must deal with is the order of the bytes as they are stored in your golfResult (1) array. Depending on the source these bytes the first (golfResult[i]) could be the least (little endian) or most (big endian) significant byte. If you assemble the 4 bytes in the wrong order then your resulting float value will be incorrect (2).

可以,并且我们提供的代码确实可以,使用整数类型变量作为n 个字节的存储,而不将它们视为整数本身.也就是说,如果您有一个 int32_t * 类型的指针,从中加载一个值并将其存储在 int32_t 变量中,那么您刚刚从一个位置复制了 4 个字节到另一个保持他们的顺序.

You can, and the code we present does, use an integer typed variable as a store for n bytes without considering them as an integer per se. That is if you have a pointer of type int32_t *, load a value from it and store it in an int32_t variable then you've just copied 4 bytes from one location to another preserving their order.

Apple 提供了 字节顺序实用程序 函数来重新排列字节-order 和 CFSwapInt32BigToHost()CFSwapInt32LittleToHost() 之一应该用于将您的 4 个字节排序为您的主机平台使用的任何顺序(请注意,您不需要要知道主机顺序,小端或大端,这些函数都知道;你只需要知道 golfResult 中的顺序).

Apple provide the Byte Order Utilities functions to rearrange the byte-order and one of CFSwapInt32BigToHost() or CFSwapInt32LittleToHost() should be used to order your 4 bytes into whatever order your host platform is using (note that you don't need to know the host order, little or big endian, these functions know that; you just need to know the order in golfResult).

最后,重要的是要知道 calloc()malloc() 和朋友返回一个指针对齐以便它可以用于任何数据类型"(参见终端中的man 3 malloc).这意味着您可以强制将此指针转换为指向任何类型的指针并加载/存储而不会出现内存对齐问题.

Finally it is important to know that calloc(), malloc() and friends return a pointer "aligned such that it can be used for any data type" (see man 3 malloc in Terminal). This means you can cast this pointer to be a pointer to any type and load/store without memory alignment issues.

现在听起来可能很复杂,但在代码中它很短很容易.像生成 bytearray 一样开始,保留字节的顺序:

Now that probably all sounds complicated, but in code it is short and easy. Start as you did to produce bytearray, preserving the order of the bytes:

unsigned char *bytearray = (unsigned char *)calloc(4, sizeof(unsigned char));
bytearray[0] = GolfResult[i]; bytearray[1] = GolfResult[i+1]; bytearray[2] = GolfResult[i+2]; bytearray[3] = GolfResult[i+3];

现在进行字节的加载、字节交换和浮动解释:

Now do the load, byte swap, and float interpretation of the bytes:

// - cast bytearray to be a pointer to
//   int32_t (used here ONLY as a 4 byte container and NOT as
//   an integer *per se*) then copy the 4 bytes to unorderedBytes
//   so the four bytes are in the same order as in bytearray.
int32_t unorderedBytes = *(int32_t *)bytearray;

// - pass those four bytes to a function to reorder them to host
//   endian order, here we pick CFSwapInt32LittleToHost, you might
//   require CFSwapInt32BigToHost
int32_t orderedBytes = CFSwapInt32LittleToHost(unorderedBytes);

// now cast the *address* of the host-ordered four bytes to
// be a float pointer and load them, interpreting them correctly
float output = *(float *)&orderedBytes;

希望更多的是帮助而不是混淆!

Hope that help more than it confuses!

注意事项:

(1) 您是否注意到变量 GolfResult 是蓝色的?这是因为您没有遵循以小写字母开头的变量命名约定.

(1) Did you notice that your variable GolfResult is coloured blue? This is because you've not followed the naming convention of starting variables with a lowercase letter.

(2) 我们这里只处理字节顺序,忽略二进制格式.大多数系统都使用 IEEE 浮点格式,如果 golfResult 中的字节来自哪里而不使用 IEEE,那么您将遇到更大的问题,因为您需要解释它们使用的任何格式.假设 IEEE 可能是安全的.

(2) We only deal here with byte order, we ignore the binary format. Most systems use IEEE floating point formats, if wherever the bytes in golfResult came from did not use IEEE you have a bigger problem as you need to interpret whatever format they used. Assuming IEEE is probably safe.

这篇关于如何在Objective C中将四字节数组转换为浮点数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆