簡體   English   中英

如何將 size_t 轉換為 double 或 int C++

[英]How to cast the size_t to double or int C++

我的問題是

我有一個 size_t 數據,但現在我想將其轉換為 double 或 int。

如果我做類似的事情

 size_t data = 99999999;
 int convertdata = data;

編譯器會報告警告。 因為它可能會溢出。

你有像 boost 這樣的方法或其他一些方法來進行轉換嗎?

演員陣容正如 Blaz Bratanic 所建議的

size_t data = 99999999;
int convertdata = static_cast<int>(data);

可能會使警告靜音(盡管原則上編譯器可以警告它喜歡的任何東西,即使有強制轉換)。

但這並沒有解決警告告訴您的問題,即從size_tint的轉換確實可能溢出。

如果可能,請設計您的程序,以便您不需要size_t值轉換為int 只需將它存儲在size_t變量中(正如您已經完成的那樣)並使用它。

轉換為double不會導致溢出,但對於非常大的size_t值可能會導致精度損失。 同樣,將size_t轉換為double沒有多大意義; 您最好將值保留在size_t變量中。

(如果您無法避免強制轉換,R Sahu 的回答有一些建議,例如在溢出時拋出異常。)

如果您的代碼已准備好處理溢出錯誤,則可以在data過大時拋出異常。

size_t data = 99999999;
if ( data > INT_MAX )
{
   throw std::overflow_error("data is larger than INT_MAX");
}
int convertData = static_cast<int>(data);

靜態投射:

static_cast<int>(data);

您可以使用 Boost numeric_cast

如果源值超出目標類型的范圍,則會引發異常,但在轉換為double時不會檢測到精度損失。

但是,無論您使用什么函數,您都應該決定在size_t中的值大於INT_MAX的情況下要發生什么。 如果您想檢測它,請使用numeric_cast或編寫您自己的代碼進行檢查。 如果您以某種方式知道它不可能發生,那么您可以使用static_cast來抑制警告,而無需運行時檢查,但在大多數情況下,成本並不重要。

假設無法重新設計程序以避免強制轉換(參考Keith Thomson 的回答):

要將 size_t 轉換為 int,您需要確保 size_t 不超過 int 的最大值。 這可以使用std::numeric_limits來完成:

int SizeTToInt(size_t data)
{
    if (data > std::numeric_limits<int>::max())
        throw std::exception("Invalid cast.");
    return std::static_cast<int>(data);
}

如果您需要將 size_t 轉換為 double,並且需要確保不會丟失精度,我認為您可以使用窄轉換(參考 Stroustrup:The C++ Programming Language,第四版):

template<class Target, class Source>
Target NarrowCast(Source v)
{
    auto r = static_cast<Target>(v);
    if (static_cast<Source>(r) != v)
        throw RuntimeError("Narrow cast failed.");
    return r;
}

我通過檢查最大整數浮點數可表示整數的限制(代碼使用 googletest)來測試使用 size_t-to-double 轉換的窄轉換:

EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() - 2 })), size_t{ IntegerRepresentableBoundary() - 2 });
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() - 1 })), size_t{ IntegerRepresentableBoundary() - 1 });
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() })), size_t{ IntegerRepresentableBoundary() });
EXPECT_THROW(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 1 }), std::exception);
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 2 })), size_t{ IntegerRepresentableBoundary() + 2 });
EXPECT_THROW(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 3 }), std::exception);
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 4 })), size_t{ IntegerRepresentableBoundary() + 4 });
EXPECT_THROW(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 5 }), std::exception);

在哪里

constexpr size_t IntegerRepresentableBoundary()
{
    static_assert(std::numeric_limits<double>::radix == 2, "Method only valid for binary floating point format.");
    return size_t{2} << (std::numeric_limits<double>::digits - 1);
}

也就是說,如果 N 是尾數中的位數,對於小於或等於 2^N 的雙精度數,可以精確表示整數。 對於 2^N 和 2^(N+1) 之間的雙精度數,可以精確表示每隔一個整數。 對於 2^(N+1) 和 2^(N+2) 之間的雙精度數,可以精確表示每四個整數,依此類推。

暫無
暫無

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

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