Veri Türleri Sorunlarını Giderme (Visual Basic)
Bu sayfada, iç veri türlerinde işlem gerçekleştirdiğinizde oluşabilecek bazı yaygın sorunlar listelenir.
Floating-Point İfadeleri Eşit Olarak Karşılaştırmaz
Kayan noktalı sayılarla (Tek Veri Türü ve Çift Veri Türü) çalışırken bunların ikili kesirler olarak depolandığını unutmayın. Bu, ikili kesir olmayan herhangi bir miktarın (k / (2 ^ n) biçiminin tamsayılar olduğu herhangi bir miktarın tam gösterimini tutamayacakları anlamına gelir. Örneğin, 0,5 (= 1/2) ve 0,3125 (= 5/16) kesin değerler olarak tutulabilirken, 0,2 (= 1/5) ve 0,3 (= 3/10) yalnızca yaklaşık değerler olabilir.
Bu kesinlik nedeniyle, kayan nokta değerleri üzerinde çalışırken tam sonuçlara güvenemezsiniz. Özellikle, teorik olarak eşit olan iki değerin biraz farklı gösterimleri olabilir.
Kayan nokta miktarlarını karşılaştırmak için |
---|
1. Ad alanında sınıfının System yöntemini kullanarak Abs farklarının Math mutlak değerini hesaplayın. 2. Kabul edilebilir bir maksimum fark belirleyin, böylece farkları daha büyük değilse, pratik amaçlarla iki miktarı eşit olarak düşünebilirsiniz. 3. Farkın mutlak değerini kabul edilebilir farkla karşılaştırın. |
Aşağıdaki örnekte iki Double
değerin hem yanlış hem de doğru karşılaştırması gösterilmektedir.
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))
Önceki örnek, anahtar sözcüğün ToStringDouble kullandığından daha iyi duyarlık belirtebilmesi için yapısının CStr
yöntemini kullanır. Varsayılan değer 15 basamaktır, ancak "G17" biçimi bunu 17 basamağı genişletir.
Mod İşleci Doğru Sonuç Döndürmüyor
Kayan nokta depolamanın kesinsiz olması nedeniyle, işlenenlerden en az biri kayan nokta olduğunda Mod İşleci beklenmeyen bir sonuç döndürebilir.
Ondalık Veri Türü kayan nokta gösterimi kullanmaz. içinde olmayan ve Double
tam olarak içinde Decimal
olan birçok sayı Single
(örneğin, 0,2 ve 0,3). Aritmetik, kayan noktadan daha yavaş olsa da Decimal
, daha iyi duyarlık elde etmek için performans düşüşlerine değer olabilir.
Kayan nokta miktarlarının kalan tamsayısını bulmak için |
---|
1. Değişkenleri olarak Decimal bildirin.2. Değerlerinin veri türü için çok büyük olması durumunda değişmez değerleri olarak zorlamak Decimal için Long değişmez değer türü karakterini D kullanın. |
Aşağıdaki örnek, kayan nokta işlenenlerinin olası kesinliklerini gösterir.
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))
Önceki örnek, anahtar sözcüğün ToStringDouble kullandığından daha iyi duyarlık belirtebilmesi için yapısının CStr
yöntemini kullanır. Varsayılan değer 15 basamaktır, ancak "G17" biçimi bunu 17 basamağı genişletir.
olduğundan zeroPointTwo
Double
, 0,2 değeri, 0,2000000000000000001 depolanmış değeriyle sonsuz yinelenen bir ikili kesirdir. 2,0'ın bu miktara bölünmesi 9,99999999999999999995 olur ve kalan değer 0,19999999999999991 olur.
için decimalRemainder
ifadesinde, değişmez değer türü karakteri D
her iki işleneni de ile zorlar Decimal
ve 0,2 kesin bir temsile sahiptir. Bu nedenle Mod
işleç beklenen kalan 0,0 değerini verir.
olarak Decimal
bildirmenin decimalRemainder
yeterli olmadığını unutmayın. Sabit değerleri Decimal
için de zorlamalısınız veya varsayılan olarak kullanır Double
ve decimalRemainder
ile aynı yanlış değeri doubleRemainder
alır.
Boole Türü Sayısal Türe Doğru Dönüştürülmüyor
Boole Veri Türü değerleri sayı olarak depolanmaz ve depolanan değerlerin sayılarla eşdeğer olması amaçlanmamıştır. Visual Basic, önceki sürümlerle uyumluluk için ve sayısal türler arasında Boolean
dönüştürme yapmak için dönüştürme anahtar sözcükleri (CType İşlevi, CBool
, CInt
vb.) sağlar. Ancak, diğer diller bazen .NET Framework yöntemleri gibi bu dönüştürmeleri farklı şekilde gerçekleştirir.
ve False
için True
eşdeğer sayısal değerlere dayalı kod yazmamalısınız. Mümkün olduğunda, değişkenlerin Boolean
kullanımını tasarlandıkları mantıksal değerlerle kısıtlamanız gerekir. ve sayısal değerleri karıştırmanız Boolean
gerekiyorsa, seçtiğiniz dönüştürme yöntemini anladığınızdan emin olun.
Visual Basic'te Dönüştürme
sayısal veri türlerini Boolean
öğesine dönüştürmek için veya CBool
dönüştürme anahtar sözcüklerini kullandığınızdaCType
, 0 olur False
ve diğer tüm değerler olurTrue
. Dönüştürme anahtar sözcüklerini kullanarak değerleri sayısal türlere dönüştürdüğünüzde Boolean
, False
0 olur ve True
-1 olur.
Çerçevede Dönüştürme
ToInt32 Ad alanında System sınıfının yöntemi Convert +1'e dönüştürülürTrue
.
Bir Boolean
değeri sayısal veri türüne dönüştürmeniz gerekiyorsa, hangi dönüştürme yöntemini kullandığınıza dikkat edin.
Karakter Değişmez Değeri Derleyici Hatası Oluşturuyor
Herhangi bir tür karakteri olmadığında, Visual Basic değişmez değerler için varsayılan veri türlerini varsayar. Karakter değişmez değeri için varsayılan tür (tırnak işareti (" "
) içine alınmış) şeklindedir String
.
Veri String
türü Char Veri Türüne genişletilmez. Başka bir deyişle, bir Char
değişkene değişmez değer atamak istiyorsanız, bir daraltma dönüştürmesi yapmanız veya sabit değeri türe Char
zorlamanız gerekir.
Bir değişkene veya sabite atanacak bir Char değişmez değeri oluşturmak için |
---|
1. Değişken veya sabiti olarak Char bildirin.2. Karakter değerini tırnak işareti ( " " ) içine alın.3. Değişmez değeri olarak zorlamak Char için değişmez değer türü karakteriyle C kapanış çift tırnak işaretini izleyin. Tür denetimi anahtarı (Option Strict Statement) ise On ve her durumda isteniyorsa bu gereklidir. |
Aşağıdaki örnek, bir değişmez değerin bir değişkene hem başarısız hem de başarılı atamalarını Char
gösterir.
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")
Çalışma zamanında başarısız olabilecekleri için daraltma dönüştürmelerini kullanmanın her zaman bir riski vardır. Örneğin, String
Char
değerin birden fazla karakter içermesi String
durumunda dönüştürme işlemi başarısız olabilir. Bu nedenle, tür karakterini kullanmak C
daha iyi programlamadır.
Dize Dönüştürme Çalışma Zamanında Başarısız Oluyor
Dize Veri Türü çok az genişletme dönüştürmesine katılır. String
yalnızca kendisine ve Object
ile genişletir ve yalnızca Char
ve Char()
(dizi Char
) ile genişletir String
. Bunun nedeni String
değişkenlerin ve sabitlerin diğer veri türlerinin içeremeyeceği değerler içerebileceğindendir.
Tür denetimi anahtarı (Option Strict Deyimi) olduğunda On
, derleyici tüm örtük daraltma dönüştürmelerine izin vermemektedir. Bu, içerenleri String
içerir. Kodunuz, .NET Framework dönüştürmeyi denemeye yönlendiren ve CType İşlevi gibi CStr
dönüştürme anahtar sözcüklerini kullanmaya devam edebilir.
Not
Bir koleksiyondaki For Each…Next
öğelerden döngü denetimi değişkenine dönüştürmeler için daraltma-dönüştürme hatası gizleniyor. Daha fazla bilgi ve örnek için , For Each... bölümündeki "Dönüştürmeleri Daraltma" bölümüne bakın. Next Deyimi.
Dönüştürme Korumasını Daraltma
Dönüştürmeleri daraltma dezavantajı, çalışma zamanında başarısız olmalarıdır. Örneğin, bir değişken "Doğru" veya "Yanlış" dışında bir String
şey içeriyorsa, değişkenine Boolean
dönüştürülemez. Noktalama karakterleri içeriyorsa, herhangi bir sayısal türe dönüştürme başarısız olur. Değişkeninizin String
her zaman hedef türün kabul edebildiği değerleri barındırdığını bilmiyorsanız, dönüştürmeyi denememelisiniz.
'den String
başka bir veri türüne dönüştürmeniz gerekiyorsa, en güvenli yordam deneme dönüştürmeyi Try... içine almaktır. Yakalamak... Finally Deyimi. Bu, çalışma zamanı hatasıyla başa çıkmanızı sağlar.
Karakter Dizileri
Hem tek Char
bir hem de bir öğe dizisi Char
olarak genişletir String
. Ancak, String
genişletilmez Char()
. Bir String
değeri diziye Char
dönüştürmek için sınıfının yöntemini System.String kullanabilirsinizToCharArray.
Anlamsız Değerler
Genel olarak, String
değerler diğer veri türlerinde anlamlı değildir ve dönüştürme son derece yapay ve tehlikelidir. Mümkün olduğunda, değişkenlerin String
kullanımını tasarlandıkları karakter dizileriyle kısıtlamanız gerekir. Hiçbir zaman diğer türlerdeki eşdeğer değerlere dayalı kod yazmamalısınız.