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

前端 未结 5 887
旧时难觅i
旧时难觅i 2020-12-25 09:48

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;
 in         


        
5条回答
  •  醉酒成梦
    2020-12-25 10:37

    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::max())
            throw std::exception("Invalid cast.");
        return std::static_cast(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
    Target NarrowCast(Source v)
    {
        auto r = static_cast(v);
        if (static_cast(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(NarrowCast(size_t{ IntegerRepresentableBoundary() - 2 })), size_t{ IntegerRepresentableBoundary() - 2 });
    EXPECT_EQ(static_cast(NarrowCast(size_t{ IntegerRepresentableBoundary() - 1 })), size_t{ IntegerRepresentableBoundary() - 1 });
    EXPECT_EQ(static_cast(NarrowCast(size_t{ IntegerRepresentableBoundary() })), size_t{ IntegerRepresentableBoundary() });
    EXPECT_THROW(NarrowCast(size_t{ IntegerRepresentableBoundary() + 1 }), std::exception);
    EXPECT_EQ(static_cast(NarrowCast(size_t{ IntegerRepresentableBoundary() + 2 })), size_t{ IntegerRepresentableBoundary() + 2 });
    EXPECT_THROW(NarrowCast(size_t{ IntegerRepresentableBoundary() + 3 }), std::exception);
    EXPECT_EQ(static_cast(NarrowCast(size_t{ IntegerRepresentableBoundary() + 4 })), size_t{ IntegerRepresentableBoundary() + 4 });
    EXPECT_THROW(NarrowCast(size_t{ IntegerRepresentableBoundary() + 5 }), std::exception);
    

    where

    constexpr size_t IntegerRepresentableBoundary()
    {
        static_assert(std::numeric_limits::radix == 2, "Method only valid for binary floating point format.");
        return size_t{2} << (std::numeric_limits::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.

提交回复
热议问题