Как привести размер 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
переменной.
(ответ Р САУ есть некоторые предложения, если вы не можете избежать броска, например, исключение при переполнении.)
вы можете использовать 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) каждое четвертое целое число может быть точно представлено и т. д.