Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Na této stránce jsou uvedeny některé běžné problémy, ke kterým může dojít při provádění operací s vnitřními datovými typy.
Floating-Point výrazy se nerovnají jako rovná
Při práci s čísly s plovoucí desetinnou čárkou (jeden datový typ a datový typ Double), nezapomeňte, že jsou uloženy jako binární zlomky. To znamená, že nemohou obsahovat přesnou reprezentaci jakéhokoli množství, které není binární zlomek (ve tvaru k / (2 ^ n), kde k a n jsou celá čísla). Například 0,5 (= 1/2) a 0,3125 (= 5/16) lze uchovávat jako přesné hodnoty, zatímco 0,2 (= 1/5) a 0,3 (= 3/10) mohou být pouze aproximace.
Z důvodu této nepřesné opravy nemůžete při práci s hodnotami s plovoucí desetinou čárkou spoléhat na přesné výsledky. Konkrétně dvě hodnoty, které jsou teoreticky stejné, mohou mít mírně odlišné reprezentace.
| Porovnání množství s plovoucí desetinou čárkou |
|---|
| 1. Pomocí metody Math třídy v oboru názvů vypočítejte absolutní hodnotu jejich rozdílu.SystemAbs 2. Určete přijatelný maximální rozdíl, abyste mohli vzít v úvahu dvě množství, která mají být rovna pro praktické účely, pokud jejich rozdíl není větší. 3. Porovnejte absolutní hodnotu rozdílu s přijatelným rozdílem. |
Následující příklad ukazuje nesprávné i správné porovnání dvou Double hodnot.
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))
Předchozí příklad používá ToString metodu Double struktury, aby bylo možné určit lepší přesnost než klíčové CStr slovo používá. Výchozí hodnota je 15 číslic, ale formát G17 ho rozšiřuje na 17 číslic.
Operátor Mod nevrací přesný výsledek.
Vzhledem k nepřesnostem úložiště s plovoucí desetinou čárkou může operátor Mod vrátit neočekávaný výsledek, pokud je alespoň jeden z operandů s plovoucí desetinou čárkou.
Datový typ Decimal nepoužívá reprezentaci s plovoucí desetinnou čárkou. Mnoho čísel, která jsou neexaktní Single a Double jsou přesná Decimal (například 0,2 a 0,3). I když je aritmetika pomalejší Decimal než u plovoucí desetinné čárky, může se stát, že snížení výkonu dosáhnete lepší přesnosti.
| Vyhledání celočíselného zbytku množství s plovoucí desetinou čárkou |
|---|
1. Deklarujte proměnné jako Decimal.2. Znak literálového typu D použijte k vynucení literálů Decimal, pokud jsou jejich hodnoty pro datový typ příliš velké Long . |
Následující příklad ukazuje potenciální nepřesnost operandů s plovoucí desetinou čárkou.
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))
Předchozí příklad používá ToString metodu Double struktury, aby bylo možné určit lepší přesnost než klíčové CStr slovo používá. Výchozí hodnota je 15 číslic, ale formát G17 ho rozšiřuje na 17 číslic.
Protože zeroPointTwo je Double, jeho hodnota 0,2 je nekonečné opakování binární zlomek s uloženou hodnotou 0,200000000000001. Vydělením 2,0 tímto množstvím je výsledkem 9,9999999999999999999999999999999999.
Ve výrazu pro decimalRemaindermá znak D literálového typu přesnou reprezentaci oba operandy Decimala 0,2.
Mod Operátor proto získá očekávaný zbytek hodnoty 0,0.
Všimněte si, že není dostačující k deklaraci decimalRemainder jako Decimal. Musíte také vynutit literály , Decimalnebo používají Double ve výchozím nastavení a decimalRemainder obdrží stejnou nepřesnou hodnotu jako doubleRemainder.
Logický typ se nepřevádí na číselný typ přesně.
Logické hodnoty datového typu nejsou uloženy jako čísla a uložené hodnoty nejsou určeny jako ekvivalentní k číslům. Kvůli kompatibilitě se staršími verzemi poskytuje Jazyk Visual Basic klíčová slova převodu (CType – operátorCBool , CIntatd.) pro převod mezi Boolean a číselnými typy. Jiné jazyky však někdy provádějí tyto převody odlišně, stejně jako metody rozhraní .NET Framework.
Nikdy byste neměli psát kód, který spoléhá na ekvivalentní číselné hodnoty pro True a False. Kdykoli je to možné, měli byste omezit použití proměnných Boolean na logické hodnoty, pro které jsou navrženy. Pokud je nutné kombinovat Boolean a číselné hodnoty, ujistěte se, že rozumíte metodě převodu, kterou vyberete.
Převod v jazyce Visual Basic
Při použití CType klíčových slov nebo CBool převodu k převodu číselných datových typů na Boolean, 0 se stane False a všechny ostatní hodnoty se stanou True. Když převedete Boolean hodnoty na číselné typy pomocí klíčových slov převodu, False stane se 0 a True stane se -1.
Převod v rozhraní
Metoda ToInt32Convert třídy v System oboru názvů se True převede na +1.
Pokud je nutné převést Boolean hodnotu na číselný datový typ, dávejte pozor, jakou metodu převodu používáte.
Literál znaku generuje chybu kompilátoru
Bez jakýchkoli znaků typu předpokládá Jazyk Visual Basic výchozí datové typy pro literály. Výchozí typ literálu znaku uzavřený v uvozovkách (" ") je String.
Datový String typ se nerozšíruje na datový typ Char. To znamená, že pokud chcete přiřadit literál proměnné Char , musíte provést zužující převod nebo vynutit literál na Char typ.
| Vytvoření literálu Char pro přiřazení proměnné nebo konstanty |
|---|
1. Deklarujte proměnnou nebo konstantu jako Char.2. Uzavřete hodnotu znaku do uvozovek ( " ").3. Postupujte podle uzavírací uvozovky se znakem C literálového typu, aby literál vynutil .Char To je nezbytné, pokud je Onpřepínač kontroly typů (Příkaz Striktní příkaz option) a je žádoucí v každém případě. |
Následující příklad ukazuje neúspěšná i úspěšná přiřazení literálu k Char proměnné.
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")
Při používání zužujících převodů je vždy riziko, protože v době běhu můžou selhat. Například převod z String na Char může selhat, pokud String hodnota obsahuje více než jeden znak. Proto je lepší programování použít C znak typu.
Převod řetězce selže za běhu
Datový typ String se účastní velmi málo rozšiřujících převodů.
String rozšiřuje pouze na sebe a Object, a pouze Char a Char() ( Char pole) rozšířit na String. Důvodem je to, že String proměnné a konstanty mohou obsahovat hodnoty, které jiné datové typy nemohou obsahovat.
Pokud je Onpřepínač kontroly typů (Option Strict Statement) , kompilátor zakáže všechny implicitní zúžení převodů. To zahrnuje ty, které se týkají String. Váš kód může stále používat klíčová slova převodu, jako CStr je a CType Operator, které nasměrují rozhraní .NET Framework k pokusu o převod.
Poznámka:
Chyba zužujícího převodu je potlačena pro převody z prvků v For Each…Next kolekci na řídicí proměnnou smyčky. Další informace a příklady najdete v části Zúžení převodů v části Pro každý z nich... Next – příkaz.
Zužující ochrana převodu
Nevýhodou zužování převodů je, že v době běhu můžou selhat. Pokud například proměnná String obsahuje cokoli jiného než True nebo False, nelze ji převést na Boolean. Pokud obsahuje interpunkční znaky, převod na libovolný číselný typ selže. Pokud nevíte, že proměnná String vždy obsahuje hodnoty, které cílový typ může přijmout, neměli byste zkusit převod.
Pokud je nutné převést z String jiného datového typu, nejbezpečnější postup je uzavřít pokus o převod do try... Chytit... Příkaz Finally. To vám umožní vyřešit selhání za běhu.
Pole znaků
Jeden Char prvek i pole Char prvků se rozšiřuje na String. Nicméně, String nerozšíruje na Char(). Chcete-li převést String hodnotu na Char pole, můžete použít ToCharArray metodu System.String třídy.
Bezvýznamné hodnoty
Obecně platí, že String hodnoty nejsou smysluplné v jiných datových typech a převod je vysoce umělá a nebezpečná. Kdykoli je to možné, měli byste omezit použití proměnných String na sekvence znaků, pro které jsou navrženy. Nikdy byste neměli psát kód, který spoléhá na ekvivalentní hodnoty v jiných typech.