Overflow Domande su carri e carri × interi
-
27-09-2019 - |
Domanda
1) È questo unoverflowable?
long long v1, v2, result;
[..]
result = ((long double) v1 / v2) * 1000000LL;
1.a) Posso lasciare fuori il LL sulla costante? E perché.
2) In alternativa è questa variazione senza un ok galleggiante?
long long l1, l2, result;
[..]
result = (1000000 * (v1 / v2) + v1 % v2);
2.a) che ha più le spese generali? Il 1 ° o questo esempio?
3) Can galleggia sempre troppo pieno, o semplicemente avvolgere di valori 'sane'?
Soluzione
Sì, il risultato nell'esempio (1) potrebbero facilmente traboccare se, per esempio, v1 = 1.000.000 miliardi e v2 = 1. Non hanno bisogno della LL su quel costante, perché è abbastanza piccolo per adattarsi in un int
(sotto la maggior parte implementazioni, in ogni caso).
(2) che possono traboccare altrettanto bene come ad esempio 1 se v1 e v2 sono come le ho dato.
Il primo esempio è più costose, come aritmetica in virgola mobile è più costoso di aritmetica intera.
(3) Galleggianti può certamente troppo pieno e le conseguenze sono a carico di attuazione.
Come Arjit ha fatto notare, è possibile impedire un overflow controllando il valore di V1 prima di eseguire il calcolo. Se v1 potrebbe essere negativo si avrebbe inoltre necessario verificare la versione negativa, e forse la seguente potrebbe essere meglio ...
if ((LONG_LONG_MAX / 1000000) > V1)
{
...
}
Se siete veramente contro il limite si potrebbe dare voi stessi un po 'più spazio dichiarando le variabili da unsigned
.
In seguito - Modifica per correggere errori sottolineato da Arjit
.Altri suggerimenti
In primo luogo
- se facendo INT o Long calcolo dont coinvolgere galleggiante ad esso. Perché il tuo risultato nella prima parte avrebbe molti valori diversi che sono quasi uguali.
Poiché (float) v1 / v2 = ab.cdef. // dove CDEF può variare.
Il tuo secondo implementazione può anche causare troppo pieno se v1 = 2 ^ 15 e v2 = 1
quindi, se siete alla ricerca di troppo pieno e la sicurezza si dovrebbe sempre verificare
come 2 ^ 18 / costante che è 1000000 in questo caso
così
if(2^18/Constant > v1)
result = (1000000 * (v1 / v2) + v1 % v2);
Questo sarebbe alcuna prova hack.
Spero che questo aiuti