Hoe de Size_T uit te brengen naar Dubbel of int C++

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_tnaar intecht kan overlopen.

Ontwerp uw programma, zodat u niet nodig hebt om een ​​size_twaarde toe te voegen aan int. Bewaar het gewoon in een size_tvariabele (zoals u al hebt gedaan) en gebruik dat.

Converteren naar doublezal geen overloop veroorzaken, maar het kan resulteren in een verlies van precisie voor een zeer grote size_twaarde. Nogmaals, het is niet logisch om een ​​size_tnaar een doublete converteren; Je bent nog steeds beter af om de waarde in een size_tvariabele 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 datate 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_tgroter is dan INT_MAX. Als je het wilt detecteren, gebruik dan numeric_castof schrijf je eigen code om te controleren. Als je op de een of andere manier weet dat dit onmogelijk kan gebeuren, kun je static_castgebruiken 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.

Other episodes