mi viene paranoico che una di queste funzioni possono dare un risultato errato in questo modo:Il cast di `std :: floor()` e `std :: ceil()` nel tipo intero dà sempre il risultato corretto?
std::floor(2000.0/1000.0) --> std::floor(1.999999999999) --> 1
or
std::ceil(18/3) --> std::ceil(6.000000000001) --> 7
può succedere una cosa del genere? Se esiste effettivamente un rischio come questo, ho intenzione di utilizzare le funzioni seguenti per lavorare in sicurezza. Ma è davvero necessario?
constexpr long double EPSILON = 1e-10;
intmax_t GuaranteedFloor(const long double & Number)
{
if (Number > 0)
{
return static_cast<intmax_t>(std::floor(Number) + EPSILON);
}
else
{
return static_cast<intmax_t>(std::floor(Number) - EPSILON);
}
}
intmax_t GuaranteedCeil(const long double & Number)
{
if (Number > 0)
{
return static_cast<intmax_t>(std::ceil(Number) + EPSILON);
}
else
{
return static_cast<intmax_t>(std::ceil(Number) - EPSILON);
}
}
(Nota: sto assumendo che il dato 'long double' argomento si inserisce nel 'intmax_t' tipo di ritorno.)
Penserei che quegli esempi sarebbero sicuri (numeri interi, entro la precisione del punto di virgola mobile) ma, per esempio, "3.3/1.1" potrebbe concepibilmente dare "non precisamente 3". – TripeHound
'EPSILON' non ti salverà. È la più piccola differenza significativa di ** a 1,0 **, ovvero il valore più piccolo che è possibile aggiungere a 1,0 per ottenere un valore diverso. Se il risultato potrebbe essere più grande o più piccolo di 1.0, sarà necessario un diverso EPSILON. Se pensi di aver bisogno di 'EPSILON' per qualcosa, è probabile che stai per introdurre un bug molto sottile nel tuo software. – DevSolar