Устранение неполадок, связанных с типами данных (Visual Basic)Troubleshooting Data Types (Visual Basic)

На этой странице перечислены некоторые распространенные проблемы, которые могут возникнуть при выполнении операций с внутренними типами данных.This page lists some common problems that can occur when you perform operations on intrinsic data types.

Выражения с плавающей запятой не считаются равнымиFloating-Point Expressions Do Not Compare as Equal

При работе с числами с плавающей запятой (один тип данных и тип данных Double) помните, что они хранятся в виде двоичных дробей.When you work with floating-point numbers (Single Data Type and Double Data Type), remember that they are stored as binary fractions. Это означает, что они не могут содержать точное представление любого количества, которое не является двоичной дробью (в форме k/(2 ^ n), где k и n являются целыми числами).This means they cannot hold an exact representation of any quantity that is not a binary fraction (of the form k / (2 ^ n) where k and n are integers). Например, 0,5 (= 1/2) и 0,3125 (= 5/16) могут храниться как точные значения, тогда как 0,2 (= 1/5) и 0,3 (= 3/10) могут быть только приближениями.For example, 0.5 (= 1/2) and 0.3125 (= 5/16) can be held as precise values, whereas 0.2 (= 1/5) and 0.3 (= 3/10) can be only approximations.

Из-за этого неточности нельзя полагаться на точные результаты при работе с значениями с плавающей запятой.Because of this imprecision, you cannot rely on exact results when you operate on floating-point values. В частности, два значения, которые теоретически равны, могут иметь несколько различных представлений.In particular, two values that are theoretically equal might have slightly different representations.

Сравнение количества с плавающей запятойTo compare floating-point quantities
1. Вычислите абсолютное значение их разности с помощью Abs метода Math класса в System пространстве имен.1. Calculate the absolute value of their difference by using the Abs method of the Math class in the System namespace.
2. Определите допустимое максимальное различие, чтобы можно было считать, что два количества равны для практических целей, если их отличие больше.2. Determine an acceptable maximum difference, such that you can consider the two quantities to be equal for practical purposes if their difference is no larger.
3. Сравните абсолютное значение разницы с приемлемой разницей.3. Compare the absolute value of the difference to the acceptable difference.

В следующем примере демонстрируется неправильное и правильное сравнение двух Double значений.The following example demonstrates both incorrect and correct comparison of two Double values.

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))

В предыдущем примере используется ToString метод Double структуры, чтобы он мог указать лучшую точность, чем CStr использование ключевого слова.The previous example uses the ToString method of the Double structure so that it can specify better precision than the CStr keyword uses. По умолчанию используется 15 цифр, но формат "G17" расширяет его до 17 цифр.The default is 15 digits, but the "G17" format extends it to 17 digits.

Оператор Mod не возвращает точный результатMod Operator Does Not Return Accurate Result

Из-за неправильной точности хранилища с плавающей запятой оператор Mod может вернуть непредвиденный результат, если хотя бы один из операндов является плавающей запятой.Because of the imprecision of floating-point storage, the Mod Operator can return an unexpected result when at least one of the operands is floating-point.

Тип данных Decimal не использует представление с плавающей запятой.The Decimal Data Type does not use floating-point representation. Многие числа, неточные в Single и Double , являются точными в Decimal (например, 0,2 и 0,3).Many numbers that are inexact in Single and Double are exact in Decimal (for example 0.2 and 0.3). Хотя арифметические операции выполняются медленнее Decimal , чем в с плавающей запятой, может возникнуть снижение производительности, чтобы добиться лучшей точности.Although arithmetic is slower in Decimal than in floating-point, it might be worth the performance decrease to achieve better precision.

Поиск целочисленного остатка количества с плавающей запятойTo find the integer remainder of floating-point quantities
1. Объявите переменные как Decimal .1. Declare variables as Decimal.
2. Используйте символ типа литерала D для принудительного использования литералов в Decimal , если их значения слишком велики для Long типа данных.2. Use the literal type character D to force literals to Decimal, in case their values are too large for the Long data type.

В следующем примере показана потенциальная неточность операндов с плавающей запятой.The following example demonstrates the potential imprecision of floating-point operands.

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))

В предыдущем примере используется ToString метод Double структуры, чтобы он мог указать лучшую точность, чем CStr использование ключевого слова.The previous example uses the ToString method of the Double structure so that it can specify better precision than the CStr keyword uses. По умолчанию используется 15 цифр, но формат "G17" расширяет его до 17 цифр.The default is 15 digits, but the "G17" format extends it to 17 digits.

Так как zeroPointTwo имеет Double значение, его значением для 0,2 является бесконечная повторяющаяся двоичная дробь с сохраненным значением 0.20000000000000001.Because zeroPointTwo is Double, its value for 0.2 is an infinitely repeating binary fraction with a stored value of 0.20000000000000001. При делении 2,0 на это количество выдается 9.9999999999999995 с остатком от 0.19999999999999991.Dividing 2.0 by this quantity yields 9.9999999999999995 with a remainder of 0.19999999999999991.

В выражении для decimalRemainder символ типа литерала D принуждает оба операнда к Decimal , и 0,2 имеет точное представление.In the expression for decimalRemainder, the literal type character D forces both operands to Decimal, and 0.2 has a precise representation. Поэтому Mod оператор возвращает ожидаемый остаток от деления 0,0.Therefore the Mod operator yields the expected remainder of 0.0.

Обратите внимание, что объявление как не является достаточным decimalRemainder Decimal .Note that it is not sufficient to declare decimalRemainder as Decimal. Необходимо также принудительно задать литералы Decimal или использовать Double по умолчанию и получить decimalRemainder то же неточное значение, что и doubleRemainder .You must also force the literals to Decimal, or they use Double by default and decimalRemainder receives the same inaccurate value as doubleRemainder.

Логический тип не преобразуется в числовой тип точноBoolean Type Does Not Convert to Numeric Type Accurately

Значения логических типов данных не хранятся в виде чисел, а хранимые значения не должны быть эквивалентны числам.Boolean Data Type values are not stored as numbers, and the stored values are not intended to be equivalent to numbers. Для совместимости с более ранними версиями Visual Basic предоставляет ключевые слова преобразования (Функция CType, CBool , CInt и т. д.) для преобразования между Boolean и числовыми типами.For compatibility with earlier versions, Visual Basic provides conversion keywords (CType Function, CBool, CInt, and so on) to convert between Boolean and numeric types. Однако другие языки иногда выполняют эти преобразования по-разному, так же как и методы .NET Framework.However, other languages sometimes perform these conversions differently, as do the .NET Framework methods.

Никогда не следует писать код, основанный на эквивалентных числовых значениях для True и False .You should never write code that relies on equivalent numeric values for True and False. Везде, где это возможно, следует ограничить использование Boolean переменных логическими значениями, для которых они предназначены.Whenever possible, you should restrict usage of Boolean variables to the logical values for which they are designed. Если необходимо смешивать Boolean и числовые значения, убедитесь, что вы понимаете выбранный метод преобразования.If you must mix Boolean and numeric values, make sure that you understand the conversion method that you select.

Преобразование в Visual BasicConversion in Visual Basic

При использовании CType CBool ключевых слов преобразования или для преобразования числовых типов данных в значение Boolean 0 становится, False а все остальные значения становятся True недоступными.When you use the CType or CBool conversion keywords to convert numeric data types to Boolean, 0 becomes False and all other values become True. При преобразовании Boolean значений в числовые типы с помощью ключевых слов преобразования оно False преобразуется в 0 и True преобразуется в значение-1.When you convert Boolean values to numeric types by using the conversion keywords, False becomes 0 and True becomes -1.

Преобразование в платформеConversion in the Framework

ToInt32Метод Convert класса в System пространстве имен преобразуется True в + 1.The ToInt32 method of the Convert class in the System namespace converts True to +1.

Если необходимо преобразовать Boolean значение в числовой тип данных, будьте внимательны в том, какой метод преобразования используется.If you must convert a Boolean value to a numeric data type, be careful about which conversion method you use.

Символьный литерал создает ошибку компилятораCharacter Literal Generates Compiler Error

В отсутствие каких бы то ни было символов типа Visual Basic предполагает наличие типов данных по умолчанию для литералов.In the absence of any type characters, Visual Basic assumes default data types for literals. Тип по умолчанию для символьного литерала, заключенный в кавычки ( " " ), — это String .The default type for a character literal — enclosed in quotation marks (" ") — is String.

StringТип данных не расширяется до типа данных char.The String data type does not widen to the Char Data Type. Это означает, что если необходимо присвоить литерал Char переменной, необходимо либо выполнить сужение преобразования, либо принудительно применить литерал к Char типу.This means that if you want to assign a literal to a Char variable, you must either make a narrowing conversion or force the literal to the Char type.

Создание литерала Char для присвоения переменной или константеTo create a Char literal to assign to a variable or constant
1. Объявите переменную или константу как Char .1. Declare the variable or constant as Char.
2. заключите значение символа в кавычки ( " " ).2. Enclose the character value in quotation marks (" ").
3. Используйте закрывающую двойную кавычку с символом типа литерала, чтобы присвоить C литералу значение Char .3. Follow the closing double quotation mark with the literal type character C to force the literal to Char. Это необходимо, если параметр проверки типов (оператор Option строго) имеет значение On и желательно в любом случае.This is necessary if the type checking switch (Option Strict Statement) is On, and it is desirable in any case.

В следующем примере показаны неудачные и успешные назначения литерала Char переменной.The following example demonstrates both unsuccessful and successful assignments of a literal to a Char variable.

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")

При использовании сужающих преобразований всегда возникает риск, так как они могут завершиться ошибкой во время выполнения.There is always a risk in using narrowing conversions, because they can fail at run time. Например, преобразование из String в Char может завершиться ошибкой, если String значение содержит более одного символа.For example, a conversion from String to Char can fail if the String value contains more than one character. Поэтому в программировании лучше использовать C символ типа.Therefore, it is better programming to use the C type character.

Сбой преобразования строки во время выполненияString Conversion Fails at Run Time

Строковый тип данных участвует в очень редких расширяющихся преобразованиях.The String Data Type participates in very few widening conversions. Stringрасширяется только до самого себя Object , и только Char и Char() ( Char массив) расширяются до String .String widens only to itself and Object, and only Char and Char() (a Char array) widen to String. Это обусловлено тем String , что переменные и константы могут содержать значения, которые не могут содержать другие типы данных.This is because String variables and constants can contain values that other data types cannot contain.

Если параметр проверки типов (оператор Option строго) имеет значение On , компилятор запрещает все неявные сужающие преобразования.When the type checking switch (Option Strict Statement) is On, the compiler disallows all implicit narrowing conversions. Сюда входят те, которые включают в себя String .This includes those involving String. Код по-прежнему может использовать ключевые слова преобразования, такие как CStr и Функция CType, которая направляет .NET Framework для попыток преобразования.Your code can still use conversion keywords such as CStr and CType Function, which direct the .NET Framework to attempt the conversion.

Примечание

Ошибка сужения преобразования подавляется для преобразований из элементов в For Each…Next коллекции в переменную управления циклом.The narrowing-conversion error is suppressed for conversions from the elements in a For Each…Next collection to the loop control variable. Дополнительные сведения и примеры см. в подразделе «сужающие преобразования» раздела For Each... Следующий оператор.For more information and examples, see the "Narrowing Conversions" section in For Each...Next Statement.

Сужение защиты от преобразованияNarrowing Conversion Protection

Недостаток сужающих преобразований заключается в том, что они могут привести к сбою во время выполнения.The disadvantage of narrowing conversions is that they can fail at run time. Например, если String переменная содержит любые значения, отличные от "true" или "false", она не может быть преобразована в Boolean .For example, if a String variable contains anything other than "True" or "False," it cannot be converted to Boolean. Если он содержит знаки препинания, преобразование в любой числовой тип завершается ошибкой.If it contains punctuation characters, conversion to any numeric type fails. Если вы не уверены, что String переменная всегда содержит значения, которые тип назначения может принять, не следует пытаться выполнить преобразование.Unless you know that your String variable always holds values that the destination type can accept, you should not try a conversion.

При необходимости преобразования из String в другой тип данных наиболее надежная процедура заключается в том, чтобы заключить попытку преобразования в try... Перехватить... Оператор finally.If you must convert from String to another data type, the safest procedure is to enclose the attempted conversion in the Try...Catch...Finally Statement. Это позволяет справиться с ошибкой во время выполнения.This lets you deal with a run-time failure.

Массивы символовCharacter Arrays

Один Char и массив Char элементов, которые расширяются до String .A single Char and an array of Char elements both widen to String. Однако не String расширяется до Char() .However, String does not widen to Char(). Чтобы преобразовать String значение в Char массив, можно использовать ToCharArray метод System.String класса.To convert a String value to a Char array, you can use the ToCharArray method of the System.String class.

Бессмысленные значенияMeaningless Values

Как правило, String значения не имеют смысла в других типах данных, а преобразование является очень искусственным и опасным.In general, String values are not meaningful in other data types, and conversion is highly artificial and dangerous. Везде, где это возможно, следует ограничить использование String переменных последовательностями символов, для которых они предназначены.Whenever possible, you should restrict usage of String variables to the character sequences for which they are designed. Никогда не следует писать код, основанный на эквивалентных значениях других типов.You should never write code that relies on equivalent values in other types.

См. также разделSee also