casting — Как привести size_t к удвоению или переполнению стека.

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

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

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

 size_t data = 99999999;
int convertdata = data;

компилятор выдаст предупреждение. потому что это может быть переполнено.

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

27

Решение

В ролях, как предложил Блаз Братаник:

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

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

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

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

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

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

41

Другие решения

Статическое приведение:

static_cast<int>(data);
12

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

Это вызывает исключение, если исходное значение выходит за пределы диапазона целевого типа, но оно не обнаруживает потерю точности при преобразовании в double,

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

9

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

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

Для приведения типа size_t к int необходимо убедиться, что size_t не превышает максимальное значение типа int. Это можно сделать с помощью СТД :: 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 к удвоению, и вам нужно убедиться, что вы не теряете точность, я думаю, вы можете использовать узкое приведение (см. Страуструп: Язык программирования 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) каждое четвертое целое число может быть точно представлено, и так далее.

1
По вопросам рекламы [email protected]