How to cast the size_t to double or int C++

匆匆过客 提交于 2019-12-20 10:29:32

问题


My question is that

I have a size_t data, but now I want to convert it to double or 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?


回答1:


A cast, as Blaz Bratanic suggested:

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.

If at all possible, design your program so you don't need to convert a size_t value to int. Just store it in a size_t variable (as you've already done) and use that.

Converting to double will not cause an overflow, but it could result in a loss of precision for a very large size_t value. Again, it doesn't make a lot of sense to convert a size_t to a double; you're still better off keeping the value in a size_t variable.

(R Sahu's answer has some suggestions if you can't avoid the cast, such as throwing an exception on overflow.)




回答2:


Static cast:

static_cast<int>(data);



回答3:


If your code is prepared to deal with overflow errors, you can throw an exception if data is too large.

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



回答4:


You can use 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.

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. If you want to detect it use numeric_cast or write your own code to check. 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.




回答5:


Assuming that the program cannot be redesigned to avoid the cast (ref. Keith Thomson's answer):

To cast from size_t to int you need to ensure that the size_t does not exceed the maximum value of the int. This can be done using 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):

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):

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. For doubles between 2^N and 2^(N+1), every other integer can be exactly represented. For doubles between 2^(N+1) and 2^(N+2) every fourth integer can be exactly represented, and so on.



来源:https://stackoverflow.com/questions/22184403/how-to-cast-the-size-t-to-double-or-int-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!