我想将浮点数从小端转换为大端,但我无法做到。 我已经成功转换了int数字的endianess但是有人可以帮助浮点数
答案 0 :(得分:3)
#include <cstring> // for std::memcpy
#include <algorithm> // for std::reverse
#include <iterator> // For C++11 std::begin() and std::end()
// converting from float to bytes for writing out
float f = 10.0;
char c[sizeof f];
std::memcpy(c,&f,sizeof f);
std::reverse(std::begin(c),std::end(c)); // begin() and end() are C++11. For C++98 say std::reverse(c,c + sizeof f);
// ... write c to network, file, whatever ...
走向另一个方向:
char c[] = { 41, 36, 42, 59 };
static_assert(sizeof(float) == sizeof c,"");
std::reverse(std::begin(c),std::end(c));
float f;
std::memcpy(&f,c,sizeof f);
浮点值的表示是实现定义的,因此由此产生的值在不同的实现之间可能是不同的。也就是说,10.0字节交换可能是1.15705e-041,或其他东西,或者它可能根本不是有效的浮点数。
然而,任何使用IEEE 754的实现(大多数都可以,并且您可以通过查看std::numeric_limits<float>.is_iec559
是否为真来检查)应该给出相同的结果。 (std::numeric_limits
来自#include <limits>
。)
上面的代码将float转换为字节,修改字节,然后将这些字节转换回float。如果您有一些想要作为float读取的字节值,那么您可以将char数组的值设置为您的字节,然后使用memcpy()
,如上所示(std::reverse()
之后的行)将这些字节放入f
。
通常人们会建议使用reinterpret_cast进行此类操作,但我认为避免强制转换是件好事。人们经常错误地使用它们,并且在没有意识到的情在这种情况下,reinterpret_cast可以合法使用,但我仍然认为最好避免它。
虽然它确实将4行减少到1 ......
std::reverse(reinterpret_cast<char*>(&f),reinterpret_cast<char*>(&f) + sizeof f);
这里有一个为什么你不应该使用reinterpret_cast的例子。以下可能会起作用,但可能导致未定义的行为。既然它有效,你甚至可能不会注意到你做错了什么,这是最不可取的结果之一。
char c[] = { 41, 36, 42, 59 };
static_assert(sizeof(float) == sizeof c,"");
float f = *reinterpret_cast<float*>(&c[0]);
答案 1 :(得分:0)
执行此类操作的正确方法是使用联合。
union float_int {
float m_float;
int32_t m_int;
};
这样你可以将你的浮点数转换为整数,因为你已经知道如何转换你的整数字节,你就是好的。
对于双人而言,它是这样的:
union double_int {
double m_float;
int64_t m_int;
};
int32_t和int64_t通常在stdint.h中可用,boost提供这样的,Qt有自己的一组定义。只需确保整数的大小正好等于float的大小。在某些系统上,您还有很长的双重定义:
union double_int {
long double m_float;
int128_t m_int;
};
如果int128_t不起作用,您可以使用结构:
union long_double_int {
long double m_float;
struct {
int32_t m_int_low;
int32_t m_int_hi;
};
};
这可能会让你觉得在所有情况下,你可以使用字节来代替使用int:
union float_int {
float m_float;
unsigned char m_bytes[4];
};
当你发现在进行这样的转换时你不需要所有常用的转换时...因为你也可以声明:
union char_int {
int m_int;
unsigned char m_bytes[4];
};
现在您的代码看起来非常简单:
float_int fi;
char_int ci;
fi.m_float = my_float;
ci.m_bytes[0] = fi.m_bytes[3];
ci.m_bytes[1] = fi.m_bytes[2];
ci.m_bytes[2] = fi.m_bytes[1];
ci.m_bytes[3] = fi.m_bytes[0];
// now ci.m_int is the float in the other endian
fwrite(&ci, 1, 4, f);
[...snip...]
fread(&ci, 1, 4, f);
// here ci.m_int is the float in the other endian, so restore:
fi.m_bytes[0] = ci.m_bytes[3];
fi.m_bytes[1] = ci.m_bytes[2];
fi.m_bytes[2] = ci.m_bytes[1];
fi.m_bytes[3] = ci.m_bytes[0];
my_float = fi.m_float;
// now my_float was restored from the file
显然,在此示例中交换了endianess。如果要在LITTLE_ENDIAN和BIG_ENDIAN计算机上编译程序,你可能还需要知道是否确实需要进行这样的交换(检查BYTE_ENDIAN。)