私の質問は
Size_tデータがありますが、今度はそれをdoubleまたはintに変換します。
私が何かをするなら
size_t data = 99999999;
int convertdata = data;
コンパイラーは警告を報告します。多分オーバーフローするからです.
ブーストなどの方法や変換を行う他の方法はありますか?
キャスト、 Blaz Bratanicが提案したように :
size_t data = 99999999;
int convertdata = static_cast<int>(data);
は、警告を黙らせる可能性があります(ただし、キャストがあったとしても、原則としてコンパイラは好きなものについて警告できます)。
しかし、警告があなたに伝えていた問題、つまりsize_t
からint
への変換が実際にオーバーフローする可能性があるという問題は解決しません。
可能な場合は、size_t
値をint
に変換する必要がないようにしないようにプログラムを設計してください。それをsize_t
変数に格納し(既に行ったように)、それを使用します。
double
に変換してもオーバーフローは発生しませんが、非常に大きなsize_t
値に対して精度が失われる可能性があります。繰り返しますが、size_t
をdouble
に変換することはあまり意味がありません。 size_t
変数に値を保持することをお勧めします。
( R Sahuの答え キャストを回避できない場合、オーバーフロー時に例外をスローするなど、いくつかの提案があります。)
静的キャスト:
static_cast<int>(data);
コードがオーバーフローエラーを処理する準備ができている場合、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);
Boost numeric_cast
を使用できます。
これは、ソース値が宛先タイプの範囲外の場合に例外をスローしますが、double
への変換時に精度の低下を検出しません。
ただし、使用する関数が何であれ、size_t
の値がINT_MAX
よりも大きい場合にどうするかを決定する必要があります。検出する場合は、numeric_cast
を使用するか、チェックする独自のコードを記述します。何らかの理由で発生しない可能性があることがわかっている場合は、static_cast
を使用して、ランタイムチェックのコストなしで警告を抑制できますが、ほとんどの場合、コストは問題になりません。
キャストを回避するためにプログラムを再設計できないと仮定します(参照 Keith Thomson's answer ):
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、Fourth Edition):
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;
}
Size_tからdoubleへの変換にナローキャストを使用して、浮動小数点で表現可能な整数の最大値の制限を調べてテストしました(コードはgoogletestを使用しています)。
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以下のdoubleの場合、整数を正確に表すことができます。 2 ^ Nと2 ^(N + 1)の間のdoubleの場合、他のすべての整数を正確に表すことができます。 2 ^(N + 1)と2 ^(N + 2)の間のdoubleの場合、4番目の整数ごとに正確に表すことができます。