如何将size_t强制转换为double或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);

您可以使用Boostnumeric_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:C++编程语言,第四版):

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-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)之间的二重,每四个整数都可以精确地表示,依此类推

相关内容

  • 没有找到相关文章

最新更新