sirve - Cómo lanzar el size_t para doblar o int C++
size_t c++ para que sirve (5)
Puedes usar Boost numeric_cast
.
Esto genera una excepción si el valor de origen está fuera del rango del tipo de destino, pero no detecta una pérdida de precisión cuando se convierte al double
.
Sin embargo, INT_MAX
función que utilice, debe decidir qué desea que suceda en el caso de que el valor en size_t
sea mayor que INT_MAX
. Si desea detectarlo, use numeric_cast
o escriba su propio código para verificarlo. Si de alguna manera usted sabe que no es posible que ocurra, entonces puede usar static_cast
para suprimir la advertencia sin el costo de una verificación en tiempo de ejecución, pero en la mayoría de los casos el costo no importa de todos modos.
Mi pregunta es que
Tengo datos de size_t, pero ahora quiero convertirlos a double o int.
Si hago algo como
size_t data = 99999999;
int convertdata = data;
el compilador informará de advertencia. porque tal vez se desborda.
¿Tienes algún método como el impulso o algún otro método para hacer la conversión?
Reparto estático:
static_cast<int>(data);
Si su código está preparado para lidiar con errores de desbordamiento, puede lanzar una excepción si los data
son demasiado grandes.
size_t data = 99999999;
if ( data > INT_MAX )
{
throw std::overflow_error("data is larger than INT_MAX);
}
int convertData = static_cast<int>(data);
Suponiendo que el programa no pueda ser rediseñado para evitar el reparto (ref. Respuesta de Keith Thomson ):
Para realizar la conversión de size_t a int, debe asegurarse de que size_t no exceda el valor máximo de int. Esto se puede hacer usando 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);
}
Si necesita convertir desde tamaño_t a doble, y necesita asegurarse de no perder precisión, creo que puede usar un reparto estrecho (ref. Stroustrup: El lenguaje de programación C ++, Cuarta edición):
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;
}
Probé usando la conversión restringida para conversiones de size_t-to-double al inspeccionar los límites de los enteros máximos representativos de punto flotante (el código usa 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);
dónde
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);
}
Es decir, si N es el número de dígitos en la mantisa, para los dobles más pequeños o iguales a 2 ^ N, los enteros se pueden representar exactamente. Para los dobles entre 2 ^ N y 2 ^ (N + 1), todos los demás enteros se pueden representar exactamente. Para los dobles entre 2 ^ (N + 1) y 2 ^ (N + 2), se puede representar exactamente cada cuarto número entero, y así sucesivamente.
Un elenco, como Blaz Bratanic sugirió :
size_t data = 99999999;
int convertdata = static_cast<int>(data);
es probable que silencie la advertencia (aunque en principio un compilador puede advertir sobre cualquier cosa que quiera, incluso si hay un reparto).
Pero no resuelve el problema que la advertencia le decía, a saber, que una conversión de size_t
a int
realmente podría desbordarse.
Si es posible, diseñe su programa para que no necesite convertir un valor de size_t
a int
. Solo guárdelo en una variable size_t
(como ya lo ha hecho) y úselo.
La conversión al double
no causará un desbordamiento, pero podría resultar en una pérdida de precisión para un valor de size_t
muy grande. De nuevo, no tiene mucho sentido convertir un size_t
en un double
; es mejor mantener el valor en una variable size_t
.
( La respuesta de R Sahu tiene algunas sugerencias si no puedes evitar el reparto, como lanzar una excepción en el desbordamiento).