Questa è una strana peculiarità VBA. Sono stupito di non essermi mai imbattuto in questo.
Dim x As Long
x = 24 * 60 * 60 ' Overflow
x = 32767 + 1 ' Overflow.
x = 32768 + 1 ' Works fine!
così sembra che gli operatori *
e +
restituire un intero nei primi due esempi. Abbastanza sicuro, nel file di aiuto per l'operatore *
(simile per l'operatore +
):
result = number1 * number2
[...]
The data type of result is usually the same as that of the most precise expression.
I suoi letterali 24, 60 e 60 sono tutti di tipo Integer di default, quindi l'operatore *
(o +
) restituisce un numero intero, che trabocca perché il risultato è maggiore di 32.767.
Tuttavia, il valore letterale 32.768 nel terzo esempio sopra predefinito è il tipo Lungo (poiché è troppo grande per essere un numero intero) e pertanto +
restituisce un valore Long; nessun trabocco.
Il file di aiuto dice anche questo:
If [...] the data type of result is an Integer variant that overflows its legal range [...] Then result is [...] converted to a Long variant.
enfasi mia. Ora questa piccola regola suona come il buon senso, e chiunque potrebbe ragionevolmente presumere che si applica nel tuo caso. Ma i tuoi numeri sono di tipo Integer, non Variant/Integer, quindi VBA non applica questa regola! Non ha assolutamente senso per me, ma è così che è, ed è quello che dice la documentazione.
Soluzione: rendere uno degli argomenti del proprio operatore *
di un tipo più preciso di Integer (ad esempio Long) e il problema scompare.
x = CLng(24) * 60 * 60 ' Result is Long, works fine.
In realtà, e questo è probabilmente il motivo non ho mai imbattuto in questo cavillo, io faccio l'abitudine di dichiarare tutte le mie variabili intere, come a lungo, invece, a meno che non v'è una preoccupazione specifica che avere Longs, invece di Gli interi causeranno problemi con l'uso della memoria o il tempo di esecuzione (che non è quasi mai il caso). Certo, questo non sarà di aiuto nei casi in cui si opera su letterali inferiori a 32.768, perché sono predefiniti al tipo Integer.
cosa chiederete nel a comment quello che una variante/Integer è. Variant è fondamentalmente un tipo di contenitore per qualsiasi altro tipo di dati. Nel caso particolare in cui si rendono contiene un numero intero:
Dim a As Variant ' a is now Empty
a = CInt(32767) ' a is now Variant/Integer
x = a + 1 ' works fine
Ma, come osservato in precedenza, una vecchia intero semplice innesca l'errore di overflow:
Dim b As Integer
b = 32767
x = b + 1 ' overflow
Oltre a questo. - Se metto msgbox 26 * 60^2 nella finestra immediata non ci sono problemi. È un ordine di precedenza? Sembra improbabile ... –
Questo perché l'operatore '^' restituisce un Double, che elimini il problema descritto nella mia risposta di seguito. –