2013-06-26 8 views
8

Se si digita quanto segue nella finestra immediata, viene visualizzato Errore di runtime '6': Overflow.Overflow quando si moltiplicano i numeri interi e si assegna a Long

MsgBox 24 * 60 * 60 

Perché è questo?

Questo fallisce anche:

Dim giveTime As Long 
giveTime = 24 * 60 * 60 

perché è questo? giveTime è dichiarato come un tipo lungo, quindi 24 × 60 × 60 = 86400 dovrebbe adattarsi comodamente.

+0

Oltre a questo. - Se metto msgbox 26 * 60^2 nella finestra immediata non ci sono problemi. È un ordine di precedenza? Sembra improbabile ... –

+0

Questo perché l'operatore '^' restituisce un Double, che elimini il problema descritto nella mia risposta di seguito. –

risposta

22

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 
+0

Sicuramente è una stranezza! Quindi, qual è la differenza tra Variant/Integer e un intero? Presumo che uno sia dichiarato nel codice, l'altro dichiarato internamente? –

+0

o 'x = [24 * 60 * 60]' –

+1

A destra. Bene, '[]' parentesi quadre sono abbreviazioni per il metodo ['Evaluate'] (http://office.microsoft.com/client/helppreview14.aspx?AssetId=HV080005401&lcid=2057&NS=EXCEL.DEV&Version=14&tl=2&respos=0&CTT = 1 & QueryId = 0b704676-cdcb-458A-b300-1bf8775c4ed3). Quindi stai chiamando l'interprete di Excel per valutare un'espressione in VBA. Sembra qualcosa che aggiunge un sovraccarico se fatto ripetutamente, ma suppongo che sia ok se usato occasionalmente. –

1

Dopo ogni numero, luogo #. Definisce ogni numero come un doppio.Pensa a questo, ogni numero viene inserito nella memoria per il calcolo come una specie di variabile temporanea. Se si definisce ciascun numero, questo consentirà uno spazio sufficiente per i calcoli.

esempio:

Dim x As Long

x = 24 # * 60 # * 60 #

o 24 & 'indica lungo

Problemi correlati