Подтвердить что ты не робот

Как отличить size_t к double или int С++

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

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

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

 size_t data = 99999999;
 int convertdata = data;

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

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

4b9b3361

Ответ 1

Присвоение, как Блаз Братанич предложил:

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

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

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

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

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

Ответ 2

Статический бросок:

static_cast<int>(data);

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

Чтобы отбрасывать из 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, и вам нужно убедиться, что вы не потеряете точность, я думаю, вы можете использовать узкое литье (ссылка: Stroustrup: язык программирования С++, четвертое издание):

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