Mijn vraag is dat
Ik heb een Size_t-gegevens, maar nu wil ik het converteren naar dubbele of int.
Als ik iets doe als
size_t data = 99999999;
int convertdata = data;
De compiler rapporteert waarschuwing. omdat het misschien overloopt.
Heeft u een methode zoals de boost of een andere methode om de converteren te doen?
Antwoord 1, Autoriteit 100%
een cast, als Blaz Bratanic stelde aan:
size_t data = 99999999;
int convertdata = static_cast<int>(data);
zal waarschijnlijk de waarschuwing zwijgen (hoewel in principe een compiler kan waarschuwen voor alles wat het leuk vindt, zelfs als er een cast is).
Maar het lost het probleem niet op dat de waarschuwing u over vertelde, namelijk dat een conversie van size_t
naar int
echt kan overlopen.
Ontwerp uw programma, zodat u niet nodig hebt om een size_t
waarde toe te voegen aan int
. Bewaar het gewoon in een size_t
variabele (zoals u al hebt gedaan) en gebruik dat.
Converteren naar double
zal geen overloop veroorzaken, maar het kan resulteren in een verlies van precisie voor een zeer grote size_t
waarde. Nogmaals, het is niet logisch om een size_t
naar een double
te converteren; Je bent nog steeds beter af om de waarde in een size_t
variabele te houden.
(r Sahu’s antwoord heeft enkele suggesties als u de cast niet kunt vermijden, zoals het gooien van een uitzondering op overloop .)
Antwoord 2, Autoriteit 25%
Als uw code is voorbereid op overloopfouten, kunt u een uitzondering maken als data
te groot zijn.
size_t data = 99999999;
if ( data > INT_MAX )
{
throw std::overflow_error("data is larger than INT_MAX");
}
int convertData = static_cast<int>(data);
Antwoord 3, autoriteit 20%
Statische cast:
static_cast<int>(data);
Antwoord 4, autoriteit 15%
Je kunt Boost numeric_cast
.
Dit genereert een uitzondering als de bronwaarde buiten het bereik van het bestemmingstype valt, maar het detecteert geen verlies van precisie bij het converteren naar double
.
Welke functie je ook gebruikt, je moet beslissen wat je wilt dat er gebeurt in het geval dat de waarde in de size_t
groter is dan INT_MAX
. Als je het wilt detecteren, gebruik dan numeric_cast
of schrijf je eigen code om te controleren. Als je op de een of andere manier weet dat dit onmogelijk kan gebeuren, kun je static_cast
gebruiken om de waarschuwing te onderdrukken zonder de kosten van een runtime-controle, maar in de meeste gevallen doen de kosten er niet toe.
Antwoord 5, autoriteit 4%
Ervan uitgaande dat het programma niet opnieuw kan worden ontworpen om de cast te vermijden (ref. Keith Thomsons antwoord):
Om cast van size_t naar int moet u ervoor zorgen dat de size_t niet hoger is dan de maximale waarde van de int. Dit kan worden gedaan met behulp van 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);
}
Als u cast van size_t om dubbele, en je moet ervoor zorgen dat je niet verliezen precisie te doen, ik denk dat je een smalle cast gebruiken (ref Stroustrup:. De C++ Programming Language, vierde editie):
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;
}
I getest met smalle brengen voor size_t naar double conversies inspecteren van de grenzen van de maximale integers floating-point-voorstelbaar integers (code gebruik 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);
waar
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);
}
Dat wil zeggen, als n het aantal cijfers in de Mantissa is, voor verdubbeling kleiner dan of gelijk aan 2 ^ N, kunnen gehele getallen precies worden vertegenwoordigd. Voor verdubbelt tussen 2 ^ N en 2 ^ (N + 1), kan elk ander geheel getal precies worden vertegenwoordigd. Voor verdubbelt tussen 2 ^ (N + 1) en 2 ^ (N + 2) kan elk vierde geheel getal precies worden vertegenwoordigd, enzovoort.