如何将size_t转换为double或int C ++

时间:2014-03-04 22:20:48

标签: c++ casting double size-t

我的问题是

我有一个size_t数据,但现在我想将它转换为double或int。

如果我做的话

 size_t data = 99999999;
 int convertdata = data;

编译器将报告警告。因为它可能会溢出。

你有一些像boost或其他方法进行转换的方法吗?

5 个答案:

答案 0 :(得分:46)

演员,as Blaz Bratanic suggested

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's answer有一些建议,如果你无法避免强制转换,例如在溢出时抛出异常。)

答案 1 :(得分:13)

静态演员:

static_cast<int>(data);

答案 2 :(得分:11)

如果您的代码已准备好处理溢出错误,那么如果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);

答案 3 :(得分:9)

您可以使用Boost numeric_cast

如果源值超出目标类型的范围,则会引发异常,但在转换为double时,它不会检测到精度损失。

无论您使用什么功能,在size_t的值大于INT_MAX的情况下,您应该决定要发生什么。如果要检测它,请使用numeric_cast或编写自己的代码进行检查。如果您以某种方式知道它不可能发生,那么您可以使用static_cast来抑制警告,而无需运行时检查,但在大多数情况下,成本无论如何都无关紧要。

答案 4 :(得分:1)

假设程序无法重新设计以避免强制转换(参考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: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;
}

我通过检查最大整数浮点表示整数的限制(代码使用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)之间的双精度,可以精确地表示每个第四个整数,依此类推。