Adattípusok hibaelhárítása (Visual Basic)
Ez a lap felsorol néhány gyakori problémát, amelyek akkor fordulhatnak elő, ha belső adattípusokon hajt végre műveleteket.
Floating-Point kifejezések nem egyenrangúként
Ha lebegőpontos számokkal (egy adattípussal és dupla adattípussal) dolgozik, ne feledje, hogy ezek bináris törtekként vannak tárolva. Ez azt jelenti, hogy nem tartalmazhatnak pontos ábrázolást olyan mennyiségről, amely nem bináris tört (k / (2 ^ n) formában, ahol k és n egész számok. A 0,5 (= 1/2) és a 0,3125 (= 5/16) például pontos értékek, míg a 0,2 (= 1/5) és a 0,3 (= 3/10) csak közelítések lehetnek.
Emiatt a pontatlanság miatt nem támaszkodhat pontos eredményekre lebegőpontos értékek használatakor. Különösen két, elméletileg egyenlő érték némileg eltérő ábrázolásokkal rendelkezhet.
Lebegőpontos mennyiségek összehasonlítása |
---|
1. Számítsa ki a különbség abszolút értékét a Abs névtér osztályának System metódusávalMath. 2. Határozzon meg egy elfogadható maximális különbséget, hogy a két mennyiség gyakorlati szempontból egyenlő legyen, ha a különbségük nem nagyobb. 3. Hasonlítsa össze a különbség abszolút értékét az elfogadható különbségével. |
Az alábbi példa két Double
érték helytelen és helyes összehasonlítását mutatja be.
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))
Az előző példa a ToString struktúra metódusát Double használja, hogy nagyobb pontosságot adjon meg, mint a CStr
kulcsszó. Az alapértelmezett érték 15 számjegy, de a "G17" formátum 17 számjegyre bővíti.
A Mod Operátor nem ad vissza pontos eredményt
A lebegőpontos tárolás pontatlansága miatt a Mod Operátor váratlan eredményt adhat vissza, ha az operandusok közül legalább az egyik lebegőpontos.
A Decimális adattípus nem használ lebegőpontos reprezentációt. Sok olyan szám, amely nem létezik Single
, és Double
pontosak Decimal
(például 0,2 és 0,3). Bár az aritmetika lassabb Decimal
, mint a lebegőpontos, érdemes lehet a teljesítménycsökkenést elérni a jobb pontosság érdekében.
Lebegőpontos mennyiségek egész számának megkeresése |
---|
1. Deklaráljuk a változókat .Decimal 2. A literáltípus karakter D használatával kényszerítse a literálokat arra Decimal az esetre, ha az értékük túl nagy az Long adattípushoz. |
Az alábbi példa a lebegőpontos operandusok lehetséges pontatlanságát mutatja be.
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))
Az előző példa a ToString struktúra metódusát Double használja, hogy nagyobb pontosságot adjon meg, mint a CStr
kulcsszó. Az alapértelmezett érték 15 számjegy, de a "G17" formátum 17 számjegyre bővíti.
Mivel zeroPointTwo
a értéke Double
, a 0,2 értéke végtelenül ismétlődő bináris tört, amelynek tárolt értéke 0,200000000000001. A 2,0-s mennyiség 9,999999999999999999999995 0,19999999999991 maradékával osztva.
A kifejezésben decimalRemainder
a literális típusú karakter D
mindkét operandust a értékre Decimal
kényszeríti, a 0.2 pedig pontos ábrázolású. Ezért az Mod
operátor a várt fennmaradó 0,0 értéket adja.
Vegye figyelembe, hogy a deklarálása decimalRemainder
Decimal
nem elegendő. A literálokat is a értékre kell kényszerítenie Decimal
, különben alapértelmezés szerint használják Double
őket, és decimalRemainder
ugyanazt a pontatlan értéket kapja, mint a doubleRemainder
.
A logikai típus nem konvertálható pontosan numerikus típussá
A logikai adattípus értékei nem számokként vannak tárolva, és a tárolt értékek nem egyenértékűek a számokkal. A korábbi verziókkal való kompatibilitás érdekében a Visual Basic konverziós kulcsszavakat (CType függvény, CBool
, stb CInt
.) biztosít a és a számtípusok közötti Boolean
konvertáláshoz. Más nyelvek azonban néha másképp hajtják végre ezeket az átalakításokat, mint a .NET-keretrendszer metódusok.
Soha ne írjon olyan kódot, amely egyenértékű numerikus értékekre támaszkodik a és False
a esetébenTrue
. Amikor csak lehetséges, korlátoznia kell a változók használatát Boolean
azokra a logikai értékekre, amelyekhez azokat tervezték. Ha össze kell kevernie és számértékeket kell használnia Boolean
, győződjön meg arról, hogy ismeri a választott konverziós módszert.
Konvertálás a Visual Basicben
Ha a vagy CBool
a konverziós kulcsszavakat használja numerikus CType
adattípusokká Boolean
való konvertálásához, a 0 leszFalse
, és az összes többi érték lesz True
. Ha az értékeket numerikus típussá alakítja Boolean
át a konverziós kulcsszavak használatával, 0 lesz, False
és True
-1 lesz.
Átalakítás a keretrendszerben
A ToInt32 névtérben True
lévő System osztály metódusa Convert +1 lesz.
Ha egy Boolean
értéket numerikus adattípussá kell konvertálnia, ügyeljen arra, hogy melyik konverziós módszert használja.
Karakterkonstans fordítási hiba
Típuskarakterek hiányában a Visual Basic a literálok alapértelmezett adattípusait feltételezi. A karakterkonstansok alapértelmezett típusa – idézőjelek (" "
) közé zárva – a következő String
: .
Az String
adattípus nem szélesedik ki a Char adattípusra. Ez azt jelenti, hogy ha literált szeretne hozzárendelni egy Char
változóhoz, szűkítő konverziót kell végeznie, vagy a literált a Char
típushoz kell kényszerítenie.
Karakterkonstans létrehozása változóhoz vagy állandóhoz való hozzárendeléshez |
---|
1. Deklarálja a változót vagy az állandót .Char 2. A karakterértéket idézőjelek közé kell tenni ( " " ).3. Kövesse a záró dupla idézőjelet a literál típusú karakterrel C , hogy a literált a értékre kényszerítse Char . Ez akkor szükséges, ha a típus-ellenőrző kapcsoló (Option Strict Statement) a On , és ez minden esetben kívánatos. |
Az alábbi példa egy változóhoz tartozó literál Char
sikertelen és sikeres hozzárendelését mutatja be.
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")
A szűkülő konverziók használata mindig fennáll, mert futásidőben meghiúsulhatnak. A konvertálás String
Char
például meghiúsulhat, ha az String
érték több karaktert tartalmaz. Ezért jobb programozni a C
típus karaktert.
A sztringek konvertálása futásidőben meghiúsul
A sztring adattípusa nagyon kevés szélesítő konverzióban vesz részt. String
csak önmagára, a Object
és a és a Char
Char()
( Char
tömbre) szélesedik ki String
. Ennek az az oka, hogy String
a változók és az állandók tartalmazhatnak olyan értékeket, amelyeket más adattípusok nem tartalmazhatnak.
Ha a típus-ellenőrző kapcsoló (Option Strict Statement) az On
, a fordító nem engedélyezi az összes implicit szűkítési konverziót. Ide tartoznak a következők String
: . A kód továbbra is használhat konverziós kulcsszavakat, például CStr
és CType függvényt, amelyek a .NET-keretrendszer az átalakítás megkísérlésére irányítják.
Megjegyzés
A szűkítési-konvertálási hiba el van tiltva a gyűjtemény elemeiből For Each…Next
a hurokvezérlő változóba való konvertáláskor. További információkért és példákért lásd a "Konvertálások szűkítése" szakaszt az Egyes... Következő utasítás.
A konvertálás elleni védelem szűkítése
A konverziók szűkítésének hátránya, hogy futásidőben meghiúsulhatnak. Ha például egy String
változó az "Igaz" vagy a "Hamis" értéken kívül mást is tartalmaz, az nem konvertálható a értékre Boolean
. Ha írásjeleket tartalmaz, a numerikus típusra való konvertálás sikertelen. Hacsak nem tudja, hogy a String
változó mindig olyan értékeket tartalmaz, amelyeket a céltípus elfogadhat, ne próbálkozzon átalakítással.
Ha át kell konvertálnia String
egy másik adattípusra, a legbiztonságosabb eljárás az, ha a megkísérelt átalakítást a Try... Fogás... Végül utasítás. Ez lehetővé teszi a futásidejű hibák kezelését.
Karaktertömbök
Char
Egyetlen és egy elemtömb Char
is ki van szélesedve.String
Azonban String
nem szélesedik ki a értékre Char()
. Ha egy String
értéket tömbre szeretne konvertálni Char
, használhatja az ToCharArraySystem.String osztály metódusát.
Értelmetlen értékek
Az értékek általában String
nem értelmezhetők más adattípusokban, és az átalakítás rendkívül mesterséges és veszélyes. Amikor csak lehetséges, korlátoznia kell a változók használatát String
azokra a karaktersorozatokra, amelyekhez azokat tervezték. Soha ne írjon olyan kódot, amely más típusok egyenértékű értékeire támaszkodik.
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: