Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
På den här sidan visas några vanliga problem som kan uppstå när du utför åtgärder på inbyggda datatyper.
Floating-Point uttryck jämförs inte som lika
När du arbetar med flyttalsnummer (enkel datatyp och dubbel datatyp) ska du komma ihåg att de lagras som binära bråktal. Det innebär att de inte kan innehålla en exakt representation av en kvantitet som inte är en binär fraktion (av formatet k / (2 ^ n) där k och n är heltal). Till exempel kan 0,5 (= 1/2) och 0,3125 (= 5/16) hållas som exakta värden, medan 0,2 (= 1/5) och 0,3 (= 3/10) bara kan vara uppskattningar.
På grund av detta kan du inte förlita dig på exakta resultat när du använder flyttalsvärden. I synnerhet kan två värden som är teoretiskt lika ha något olika representationer.
| Så här jämför du flyttalskvantiteter |
|---|
| 1. Beräkna det absoluta värdet för skillnaden med hjälp Abs av metoden för Math klassen i System namnområdet. 2. Fastställ en godtagbar maximal skillnad, så att du kan betrakta de två kvantiteterna som lika för praktiska ändamål om skillnaden inte är större. 3. Jämför skillnadens absoluta värde med den godtagbara skillnaden. |
I följande exempel visas både felaktig och korrekt jämförelse av två Double värden.
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))
I föregående exempel används ToString metoden för Double strukturen så att den kan ange bättre precision än nyckelordet CStr använder. Standardvärdet är 15 siffror, men formatet "G17" utökar det till 17 siffror.
Mod-operatorn returnerar inte korrekt resultat
På grund av att flyttalslagringen är ogenomtränglig kan modoperatorn returnera ett oväntat resultat när minst en av operanderna är flyttal.
Decimaldatatypen använder inte flyttalsrepresentation. Många tal som är inexakta i Single och Double är exakta i Decimal (till exempel 0.2 och 0.3). Även om aritmetiken är långsammare i Decimal än i flyttal kan det vara värt prestandaminskningen för att uppnå bättre precision.
| Så här hittar du heltalsresterna av flyttalskvantiteter |
|---|
1. Deklarera variabler som Decimal.2. Använd teckentypen D literal för att framtvinga literaler till Decimal, om deras värden är för stora för Long datatypen. |
I följande exempel visas den potentiella imprecisionen av flyttalsoperor.
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))
I föregående exempel används ToString metoden för Double strukturen så att den kan ange bättre precision än nyckelordet CStr använder. Standardvärdet är 15 siffror, men formatet "G17" utökar det till 17 siffror.
Eftersom zeroPointTwo är Doubleär dess värde för 0,2 ett oändligt upprepande binärt bråk med ett lagrat värde på 0,2000000000001. Genom att dela upp 2,0 med denna kvantitet ger det 9,999999999999995 med återstoden 0,199999999999999999991.
I uttrycket för decimalRemaindertvingar teckentypen D literaltyp båda operanderna till Decimal, och 0.2 har en exakt representation. Operatören Mod ger därför den förväntade resten av 0,0.
Observera att det inte räcker att deklarera decimalRemainder som Decimal. Du måste också tvinga literalerna till Decimal, eller så använder Double de som standard och decimalRemainder får samma felaktiga värde som doubleRemainder.
Boolesk typ konverteras inte till numerisk typ korrekt
Booleska datatypvärden lagras inte som tal och de lagrade värdena är inte avsedda att motsvara tal. För kompatibilitet med tidigare versioner tillhandahåller Visual Basic konverteringsnyckelord (CType-operator, CBool, CIntoch så vidare) för att konvertera mellan Boolean och numeriska typer. Andra språk utför dock ibland dessa konverteringar på olika sätt, liksom .NET Framework-metoderna.
Du bör aldrig skriva kod som förlitar sig på motsvarande numeriska värden för True och False. När det är möjligt bör du begränsa användningen av Boolean variabler till de logiska värden som de är utformade för. Om du måste blanda Boolean och numeriska värden kontrollerar du att du förstår den konverteringsmetod som du väljer.
Konvertering i Visual Basic
När du använder nyckelorden eller konverteringen CType för att konvertera numeriska datatyper till Booleanblir False 0 och alla andra värden blir True.CBool När du konverterar Boolean värden till numeriska typer med hjälp av konverteringsnyckelorden False blir det 0 och True blir -1.
Konvertering i ramverket
Metoden ToInt32 för Convert klassen i System namnområdet konverteras True till +1.
Om du måste konvertera ett Boolean värde till en numerisk datatyp bör du vara försiktig med vilken konverteringsmetod du använder.
Teckenliteral genererar kompilatorfel
I avsaknad av tecken av någon typ förutsätter Visual Basic standarddatatyper för literaler. Standardtypen för en teckenliteral – omgiven av citattecken (" ") – är String.
Datatypen String utvidgas inte till teckendatatypen. Det innebär att om du vill tilldela en literal till en Char variabel måste du antingen göra en begränsad konvertering eller tvinga literalen Char till typen.
| Så här skapar du en Teckenliteral som ska tilldelas till en variabel eller konstant |
|---|
1. Deklarera variabeln eller konstanten som Char.2. Omsluta teckenvärdet inom citattecken ( " ").3. Följ det avslutande dubbla citattecknet med teckentypen C literal för att tvinga literalen till Char. Detta är nödvändigt om typkontrollväxeln (Alternativ strikt instruktion) är On, och det är önskvärt i alla fall. |
I följande exempel visas både misslyckade och lyckade tilldelningar av en literal till en Char variabel.
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")
Det finns alltid en risk med att använda begränsade konverteringar, eftersom de kan misslyckas vid körning. En konvertering från String till kan till Char exempel misslyckas om värdet String innehåller mer än ett tecken. Därför är det bättre programmering att använda C typtecknet.
Strängkonvertering misslyckas vid körning
Strängdatatypen deltar i mycket få bredare konverteringar.
String breddar bara till sig själv och Object, och endast Char och Char() (en Char matris) vidgas till String. Det beror på att String variabler och konstanter kan innehålla värden som andra datatyper inte kan innehålla.
När typkontrollväxeln (Alternativ strikt instruktion) är On, tillåter kompilatorn inte alla implicita begränsade konverteringar. Detta inkluderar de som involverar String. Koden kan fortfarande använda konverteringsnyckelord som CStr och CType-operator, som dirigerar .NET Framework till att försöka konvertera.
Anmärkning
Felet narrowing-conversion ignoreras för konverteringar från elementen i en For Each…Next samling till loopkontrollvariabeln. Mer information och exempel finns i avsnittet "Begränsa konverteringar" i För varje... Nästa instruktion.
Begränsa konverteringsskydd
Nackdelen med att begränsa konverteringar är att de kan misslyckas vid körning. Om en String variabel till exempel innehåller något annat än "Sant" eller "Falskt" kan den inte konverteras till Boolean. Om den innehåller skiljetecken misslyckas konverteringen till valfri numerisk typ. Om du inte vet att variabeln String alltid innehåller värden som måltypen kan acceptera bör du inte prova en konvertering.
Om du måste konvertera från String till en annan datatyp är den säkraste proceduren att omsluta konverteringsförsöket i Try... Fånga... Slutligen -instruktion. På så sätt kan du hantera ett körningsfel.
Teckenmatriser
En enskild Char och en matris med Char element vidgas Stringtill . Utvidgas dock String inte till Char(). Om du vill konvertera ett String värde till en Char matris kan du använda ToCharArray -metoden för System.String klassen.
Meningslösa värden
I allmänhet String är värden inte meningsfulla i andra datatyper och konverteringen är mycket artificiell och farlig. När det är möjligt bör du begränsa användningen av String variabler till de teckensekvenser som de är utformade för. Du bör aldrig skriva kod som förlitar sig på motsvarande värden i andra typer.