簡體   English   中英

有效地在小端和大端浮點數之間轉換

[英]Convert between little-endian and big-endian floats effectively

我有一個可以運行的軟件,它目前在little-endian架構上運行。 我也想讓它以big-endian模式運行。 無論底層系統的字節序如何,我都想將little-endian數據寫入文件。

為了實現這一點,我決定使用 boost endian 庫。 它可以有效地轉換整數。 但它不能處理浮動(和雙打)。

它在文檔中指出,“ Boost 1.59.0 將支持浮點類型”。 但是它們在1.62中仍然不受支持。

我可以假設,浮點數是有效的IEEE 754浮點數(或雙精度數)。 但是它們的字節順序可能會因底層系統而異。 據我所知,不建議在浮動上使用htonlntohl函數。 那怎么可能呢? 是否有任何頭文件庫,它也可以處理浮點數? 我找不到任何東西。

我可以將浮點數轉換為字符串,並將其寫入文件,出於多種原因(性能、磁盤空間……),我想避免使用該方法

這里:

float f = 1.2f;
auto it = reinterpret_cast<uint8_t*>(&f);
std::reverse(it, it + sizeof(f)); //f is now in the reversed endianness

不需要任何花哨的東西。

Unheilig:你是對的,但是

#include <boost/endian/conversion.hpp>


template <typename T>
inline T endian_cast(const T & t)
{
#ifdef BOOST_LITTLE_ENDIAN
    return boost::endian::endian_reverse(t);
#else
    return t;
#endif
}

或者當您使用指針時,要立即反轉,請使用:

template <typename T>
inline T endian_cast(T *t)
{
#ifdef BOOST_LITTLE_ENDIAN
    return boost::endian::endian_reverse_inplace(*t);
#else
    return t;
#endif
}

並使用它,而不是手動(或者可能容易出錯)反轉它的內容

例子:

std::uint16_t start_address() const
{
    std::uint16_t address;
    std::memcpy(&address, &data()[1], 2);
    return endian_cast(address);
}
void start_address(std::uint16_t i)
{
    endian_cast(&i);
    std::memcpy(&data()[1], &i, 2);
}

祝你好運。

在序列化 float/double 值時,我做出以下三個假設:

  1. 機器表示遵循 IEEE 754
  2. float/double 的字節序匹配整數的字節序
  3. 在 double&/int64_t& 或 float&/int32_t& 之間 reinterpret_cast-ing 的行為是明確定義的(例如,強制轉換的行為就像類型相似)。

這些假設都不是由標准保證的。 在這些假設下,以下代碼將確保以小端順序編寫雙打:

ostream out;
double someVal;
...
static_assert(sizeof(someVal) == sizeof(int64_t),
    "Endian conversion requires 8-byte doubles");
native_to_little_inplace(reinterpret_cast<int64_t&>(someVal));
out.write(reinterpret_cast<char*>(&someVal), sizeof(someVal));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM