Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa pagina elenca alcuni problemi comuni che possono verificarsi quando si eseguono operazioni sui tipi di dati intrinseci.
Floating-Point le espressioni non vengono confrontate come uguali
Quando si utilizzano numeri a virgola mobile (tipo di dati singolo e tipo di dati Double), tenere presente che vengono archiviati come frazioni binarie. Ciò significa che non possono contenere una rappresentazione esatta di qualsiasi quantità che non è una frazione binaria (della forma k / (2 ^ n) dove k e n sono interi). Ad esempio, 0,5 (= 1/2) e 0,3125 (= 5/16) possono essere mantenuti come valori precisi, mentre 0,2 (= 1/5) e 0,3 (= 3/10) possono essere solo approssimazioni.
A causa di questa imprecisione, non è possibile basarsi sui risultati esatti quando si opera su valori a virgola mobile. In particolare, due valori teoricamente uguali potrebbero avere rappresentazioni leggermente diverse.
| Per confrontare le quantità a virgola mobile |
|---|
| 1. Calcolare il valore assoluto della differenza utilizzando il Abs metodo della Math classe nello spazio dei System nomi . 2. Determinare una differenza massima accettabile, in modo da poter considerare le due quantità uguali per scopi pratici se la loro differenza non è più grande. 3. Confrontare il valore assoluto della differenza con la differenza accettabile. |
Nell'esempio seguente viene illustrato un confronto errato e corretto di due Double valori.
Dim oneThird As Double = 1.0 / 3.0
Dim pointThrees As Double = 0.333333333333333
' The following comparison does not indicate equality.
Dim exactlyEqual As Boolean = (oneThird = pointThrees)
' The following comparison indicates equality.
Dim closeEnough As Double = 0.000000000000001
Dim absoluteDifference As Double = Math.Abs(oneThird - pointThrees)
Dim practicallyEqual As Boolean = (absoluteDifference < closeEnough)
MsgBox("1.0 / 3.0 is represented as " & oneThird.ToString("G17") &
vbCrLf & "0.333333333333333 is represented as " &
pointThrees.ToString("G17") &
vbCrLf & "Exact comparison generates " & CStr(exactlyEqual) &
vbCrLf & "Acceptable difference comparison generates " &
CStr(practicallyEqual))
Nell'esempio precedente viene usato il ToString metodo della Double struttura in modo che possa specificare una precisione migliore rispetto alla CStr parola chiave utilizzata. Il valore predefinito è 15 cifre, ma il formato "G17" lo estende a 17 cifre.
L'operatore Mod non restituisce risultati accurati
A causa dell'imprecisione dell'archiviazione a virgola mobile, l'operatore Mod può restituire un risultato imprevisto quando almeno uno degli operandi è a virgola mobile.
Il tipo di dati Decimal non usa la rappresentazione a virgola mobile. Molti numeri inesattivi e Double sono esattamente in SingleDecimal (ad esempio 0,2 e 0,3). Anche se l'aritmetica è più lenta rispetto a quella a Decimal virgola mobile, potrebbe essere utile ridurre le prestazioni per ottenere una maggiore precisione.
| Per trovare il resto intero delle quantità a virgola mobile |
|---|
1. Dichiarare le variabili come Decimal.2. Usare il carattere D di tipo letterale per forzare i valori letterali in Decimal, nel caso in cui i valori siano troppo grandi per il Long tipo di dati. |
Nell'esempio seguente viene illustrata la potenziale imprecisione degli operandi a virgola mobile.
Dim two As Double = 2.0
Dim zeroPointTwo As Double = 0.2
Dim quotient As Double = two / zeroPointTwo
Dim doubleRemainder As Double = two Mod zeroPointTwo
MsgBox("2.0 is represented as " & two.ToString("G17") &
vbCrLf & "0.2 is represented as " & zeroPointTwo.ToString("G17") &
vbCrLf & "2.0 / 0.2 generates " & quotient.ToString("G17") &
vbCrLf & "2.0 Mod 0.2 generates " &
doubleRemainder.ToString("G17"))
Dim decimalRemainder As Decimal = 2D Mod 0.2D
MsgBox("2.0D Mod 0.2D generates " & CStr(decimalRemainder))
Nell'esempio precedente viene usato il ToString metodo della Double struttura in modo che possa specificare una precisione migliore rispetto alla CStr parola chiave utilizzata. Il valore predefinito è 15 cifre, ma il formato "G17" lo estende a 17 cifre.
Poiché zeroPointTwo è Double, il valore per 0,2 è una frazione binaria infinitamente ripetuta con un valore archiviato pari a 0,2000000000000000001. Dividendo 2,0 per questa quantità produce 9,99999999999999999999995 con un resto di 0,1999999999999999999999999999991.
Nell'espressione per decimalRemainder, il carattere di tipo letterale D forza entrambi gli operandi a Decimale 0.2 ha una rappresentazione precisa. Pertanto, l'operatore Mod restituisce il resto previsto di 0,0.
Si noti che non è sufficiente dichiarare decimalRemainder come Decimal. È anche necessario forzare i valori letterali in Decimaloppure usano Double per impostazione predefinita e decimalRemainder ricevono lo stesso valore impreciso di doubleRemainder.
Il tipo booleano non viene convertito in tipo numerico in modo accurato
I valori tipo di dati booleani non vengono archiviati come numeri e i valori archiviati non devono essere equivalenti ai numeri. Per la compatibilità con le versioni precedenti, Visual Basic fornisce parole chiave di conversione (operatore CType, CBool, CInte così via) per la conversione tra Boolean tipi numerici e . Tuttavia, altri linguaggi talvolta eseguono queste conversioni in modo diverso, come nei metodi di .NET Framework.
Non è mai consigliabile scrivere codice che si basa su valori numerici equivalenti per True e False. Quando possibile, è consigliabile limitare l'utilizzo delle Boolean variabili ai valori logici per i quali sono progettati. Se è necessario combinare Boolean e valori numerici, assicurarsi di comprendere il metodo di conversione selezionato.
Conversione in Visual Basic
Quando si usano le CType parole chiave o CBool di conversione per convertire i tipi di dati numerici in Boolean, 0 diventa False e tutti gli altri valori diventano True. Quando si converte Boolean valori in tipi numerici usando le parole chiave di conversione, False diventa 0 e True diventa -1.
Conversione nel framework
Il ToInt32 metodo della Convert classe nello System spazio dei nomi converte True in +1.
Se è necessario convertire un Boolean valore in un tipo di dati numerico, prestare attenzione al metodo di conversione usato.
Il valore letterale carattere genera un errore del compilatore
In assenza di caratteri di tipo, Visual Basic presuppone i tipi di dati predefiniti per i valori letterali. Il tipo predefinito per un valore letterale carattere, racchiuso tra virgolette (" ") , è String.
Il String tipo di dati non viene esteso al tipo di dati Char. Ciò significa che se si vuole assegnare un valore letterale a una Char variabile, è necessario eseguire una conversione verso un tipo più piccolo o forzare il valore letterale al Char tipo.
| Per creare un valore letterale Char da assegnare a una variabile o a una costante |
|---|
1. Dichiarare la variabile o la costante come Char.2. Racchiudere il valore del carattere tra virgolette ( " ").3. Seguire le virgolette doppie di chiusura con il carattere C di tipo letterale per forzare il valore letterale in Char. Questa operazione è necessaria se l'opzione di controllo del tipo (istruzione Option Strict) è Oned è consigliabile in ogni caso. |
Nell'esempio seguente vengono illustrate sia le assegnazioni non riuscite che le assegnazioni riuscite di un valore letterale a una Char variabile.
Dim charVar As Char
' The following statement attempts to convert a String literal to Char.
' Because Option Strict is On, it generates a compiler error.
charVar = "Z"
' The following statement succeeds because it specifies a Char literal.
charVar = "Z"c
' The following statement succeeds because it converts String to Char.
charVar = CChar("Z")
Esiste sempre un rischio nell'uso di conversioni di tipo narrowing, perché possono avere esito negativo in fase di esecuzione. Ad esempio, una conversione da String a Char può non riuscire se il String valore contiene più di un carattere. Pertanto, è preferibile programmare l'uso del C carattere di tipo.
Conversione di stringhe non riuscita in fase di esecuzione
Il tipo di dati String partecipa a pochissime conversioni più grandi.
Stringsi estende solo a se stesso e ObjectChar solo e Char() (una Char matrice) si estende a String. Ciò è dovuto al fatto che String le variabili e le costanti possono contenere valori che altri tipi di dati non possono contenere.
Quando l'opzione di controllo del tipo (istruzione Option Strict) è On, il compilatore non consente tutte le conversioni implicite di restringimento. Sono inclusi quelli che coinvolgono String. Il codice può comunque usare parole chiave di conversione come CStr e Operatore CType, che indirizzano .NET Framework a tentare la conversione.
Annotazioni
L'errore di conversione di tipo narrowing viene eliminato per le conversioni dagli elementi di una For Each…Next raccolta alla variabile di controllo del ciclo. Per altre informazioni ed esempi, vedere la sezione "Conversioni di tipo narrowing" in For Each... Istruzione successiva.
Protezione della conversione verso un tipo di dati più piccolo
Lo svantaggio delle conversioni di tipo narrowing è che possono avere esito negativo in fase di esecuzione. Ad esempio, se una String variabile contiene elementi diversi da "True" o "False", non può essere convertito in Boolean. Se contiene caratteri di punteggiatura, la conversione in qualsiasi tipo numerico ha esito negativo. A meno che non si sappia che la String variabile contiene sempre valori che il tipo di destinazione può accettare, non è consigliabile provare una conversione.
Se è necessario eseguire la conversione da String a un altro tipo di dati, la procedura più sicura consiste nel racchiudere la conversione tentata in Try... Prendere... Istruzione Finally. In questo modo è possibile gestire un errore di runtime.
Matrici di caratteri
Una singola Char matrice di Char elementi si estende a String. Tuttavia, String non si estende a Char(). Per convertire un String valore in una Char matrice, è possibile usare il ToCharArray metodo della System.String classe .
Valori senza significato
In generale, String i valori non sono significativi in altri tipi di dati e la conversione è altamente artificiale e pericolosa. Quando possibile, è consigliabile limitare l'utilizzo delle variabili alle sequenze di String caratteri per le quali sono progettate. Non scrivere mai codice che si basa su valori equivalenti in altri tipi.