Как привести размер t в double или int c++

мой вопрос в том, что

У меня есть данные size_t, но теперь я хочу преобразовать его в double или int.

Если я сделаю что-то вроде

 size_t data = 99999999;
 int convertdata = data;

компилятор сообщит предупреждение. потому что он может переполниться.

у вас есть какой-то метод, такой как boost или какой-то другой метод для преобразования?

5 ответов


бросок, как Блаз Bratanic предложил:

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

вероятно, заставит замолчать предупреждение (хотя в принципе компилятор может предупредить обо всем, что ему нравится, даже если есть приведение).

но это не решает проблему, о которой предупреждало вас предупреждение, а именно, что преобразование из size_t to int действительно может переполниться.

если это вообще возможно, создайте свою программу, чтобы вы не нужно для преобразования a size_t значение int. Просто храните его в size_t переменная (как вы уже сделали) и используйте это.

преобразование double не вызовет переполнения, но это может привести к потере точности для очень большого size_t значение. Опять же, не имеет смысла преобразовывать size_t до double; вам все равно лучше сохранить значение в size_t переменной.

(ответ Р САУ есть некоторые предложения, если вы не можете избежать броска, например, исключение при переполнении.)


статический ролях:

static_cast<int>(data);

вы можете использовать Boost numeric_cast.

это вызывает исключение, если исходное значение находится вне диапазона типа назначения, но оно не обнаруживает потерю точности при преобразовании в double.

какую бы функцию вы ни использовали, вы должны решить, что вы хотите сделать в случае, если значение в size_t больше INT_MAX. Если вы хотите обнаружить его использовать numeric_cast или написать свой собственный код для проверки. Если ты каким-то образом знаешь, ЧТО ЭТО невозможно ... возможно, тогда вы могли бы использовать static_cast чтобы подавить предупреждение без стоимости проверки времени выполнения,но в большинстве случаев стоимость не имеет значения.


Если ваш код готов справиться с ошибками переполнения, вы можете создать исключение, если 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);

предполагая, что программа не может быть переработана, чтобы избежать приведения (ref. ответ кита Томсона):

для приведения из 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, и вам нужно убедиться, что вы не потеряете точность, я думаю, вы можете использовать узкий бросок (ref. Страуструп: В 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 в double, проверив пределы максимальных целых чисел с плавающей запятой (код использует 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);

здесь

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) каждое четвертое целое число может быть точно представлено и т. д.