简体   繁体   English

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

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

My question is that我的问题是

I have a size_t data, but now I want to convert it to double or int.我有一个 size_t 数据,但现在我想将其转换为 double 或 int。

If I do something like如果我做类似的事情

 size_t data = 99999999;
 int convertdata = data;

the compiler will report warning.编译器会报告警告。 because it maybe overflow.因为它可能会溢出。

Do you have some method like the boost or some other method to do the convert?你有像 boost 这样的方法或其他一些方法来进行转换吗?

A cast, as Blaz Bratanic suggested :演员阵容正如 Blaz Bratanic 所建议的

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

is likely to silence the warning (though in principle a compiler can warn about anything it likes, even if there's a cast).可能会使警告静音(尽管原则上编译器可以警告它喜欢的任何东西,即使有强制转换)。

But it doesn't solve the problem that the warning was telling you about, namely that a conversion from size_t to int really could overflow.但这并没有解决警告告诉您的问题,即从size_tint的转换确实可能溢出。

If at all possible, design your program so you don't need to convert a size_t value to int .如果可能,请设计您的程序,以便您不需要size_t值转换为int Just store it in a size_t variable (as you've already done) and use that.只需将它存储在size_t变量中(正如您已经完成的那样)并使用它。

Converting to double will not cause an overflow, but it could result in a loss of precision for a very large size_t value.转换为double不会导致溢出,但对于非常大的size_t值可能会导致精度损失。 Again, it doesn't make a lot of sense to convert a size_t to a double ;同样,将size_t转换为double没有多大意义; you're still better off keeping the value in a size_t variable.您最好将值保留在size_t变量中。

( R Sahu's answer has some suggestions if you can't avoid the cast, such as throwing an exception on overflow.) (如果您无法避免强制转换,R Sahu 的回答有一些建议,例如在溢出时抛出异常。)

If your code is prepared to deal with overflow errors, you can throw an exception if data is too large.如果您的代码已准备好处理溢出错误,则可以在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);

You can use Boost numeric_cast .您可以使用 Boost numeric_cast

This throws an exception if the source value is out of range of the destination type, but it doesn't detect loss of precision when converting to double .如果源值超出目标类型的范围,则会引发异常,但在转换为double时不会检测到精度损失。

Whatever function you use, though, you should decide what you want to happen in the case where the value in the size_t is greater than INT_MAX .但是,无论您使用什么函数,您都应该决定在size_t中的值大于INT_MAX的情况下要发生什么。 If you want to detect it use numeric_cast or write your own code to check.如果您想检测它,请使用numeric_cast或编写您自己的代码进行检查。 If you somehow know that it cannot possibly happen then you could use static_cast to suppress the warning without the cost of a runtime check, but in most cases the cost doesn't matter anyway.如果您以某种方式知道它不可能发生,那么您可以使用static_cast来抑制警告,而无需运行时检查,但在大多数情况下,成本并不重要。

Assuming that the program cannot be redesigned to avoid the cast (ref. Keith Thomson's answer ):假设无法重新设计程序以避免强制转换(参考Keith Thomson 的回答):

To cast from size_t to int you need to ensure that the size_t does not exceed the maximum value of the int.要将 size_t 转换为 int,您需要确保 size_t 不超过 int 的最大值。 This can be done using std::numeric_limits :这可以使用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);
}

If you need to cast from size_t to double, and you need to ensure that you don't lose precision, I think you can use a narrow cast (ref. Stroustrup: The C++ Programming Language, Fourth Edition):如果您需要将 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;
}

I tested using the narrow cast for size_t-to-double conversions by inspecting the limits of the maximum integers floating-point-representable integers (code uses googletest):我通过检查最大整数浮点数可表示整数的限制(代码使用 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);

where在哪里

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);
}

That is, if N is the number of digits in the mantissa, for doubles smaller than or equal to 2^N, integers can be exactly represented.也就是说,如果 N 是尾数中的位数,对于小于或等于 2^N 的双精度数,可以精确表示整数。 For doubles between 2^N and 2^(N+1), every other integer can be exactly represented.对于 2^N 和 2^(N+1) 之间的双精度数,可以精确表示每隔一个整数。 For doubles between 2^(N+1) and 2^(N+2) every fourth integer can be exactly represented, and so on.对于 2^(N+1) 和 2^(N+2) 之间的双精度数,可以精确表示每四个整数,依此类推。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM