Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
На этой странице перечислены некоторые распространенные проблемы, которые могут возникнуть при выполнении операций с встроенными типами данных.
выражения Floating-Point не сравниваются как равные
При работе с числами с плавающей запятой (один тип данных и двойный тип данных) помните, что они хранятся в виде двоичных дробей. Это означает, что они не могут содержать точное представление любого количества, которое не является двоичной дроби (из формы k / (2 ^ n), где k и n являются целыми числами. Например, 0,5 (= 1/2) и 0,3125 (= 5/16) могут содержаться как точные значения, в то время как 0,2 (= 1/5) и 0,3 (= 3/10) могут быть только приблизиниями.
Из-за этого нерекоменции нельзя полагаться на точные результаты при работе со значениями с плавающей запятой. В частности, два значения, которые теоретически равны, могут иметь несколько разных представлений.
Сравнение значений с плавающей запятой |
---|
1. Вычислите абсолютное значение их различия с помощью Abs метода Math класса в System пространстве имен. 2. Определите допустимое максимальное различие, таким образом, что можно рассмотреть два количества, равных для практических целей, если их разница не больше. 3. Сравните абсолютное значение разницы с допустимым различием. |
В следующем примере показано неправильное и правильное сравнение двух Double
значений.
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
слово. Значение по умолчанию — 15 цифр, но формат G17 расширяет его до 17 цифр.
Оператор mod не возвращает точный результат
Из-за нерекомендуемого хранилища с плавающей запятой оператор мода может возвращать неожиданный результат, когда по крайней мере один из операндов плавающей запятой.
Тип десятичных данных не использует представление с плавающей запятой. Многие числа, которые являются нетекстными Single
и Double
точными Decimal
(например, 0.2 и 0.3). Хотя арифметика медленнее, чем в Decimal
плавающей запятой, может потребоваться снижение производительности для повышения точности.
Поиск целочисленной оставшейся части значений с плавающей запятой |
---|
1. Объявите переменные как Decimal .2. Используйте символ D литерального типа, чтобы принудительно выполнять литералы Decimal , если их значения слишком большие для Long типа данных. |
В следующем примере показано потенциальное отсутствие операндов с плавающей запятой.
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
слово. Значение по умолчанию — 15 цифр, но формат G17 расширяет его до 17 цифр.
Double
Так как zeroPointTwo
значение 0,2 является бесконечно повторяющейся двоичной дроби с сохраненным значением 0,20000000000000000000001. Деление 2.0 на это количество дает 9,99999999999999995 с оставшейся частью 0,199999999999991.
В выражении для decimalRemainder
символа D
литерального типа оба операнда Decimal
имеют точное представление, а 0,2 — точное представление.
Mod
Поэтому оператор получает ожидаемый оставшийся 0,0.
Обратите внимание, что не достаточно объявить decimalRemainder
как Decimal
. Кроме того, необходимо принудительно использовать литералы Decimal
или они используются Double
по умолчанию и получают то же неточное значение, что doubleRemainder
и decimalRemainder
.
Логический тип не преобразуется в числовой тип точно
Логические значения типа данных не хранятся в виде чисел, а сохраненные значения не предназначены для эквивалента числам. Для совместимости с более ранними версиями Visual Basic предоставляет ключевые слова преобразования (оператор CType, CBool
CInt
и т. д.) для преобразования между Boolean
числовыми типами. Однако другие языки иногда выполняют эти преобразования по-разному, как и методы .NET Framework.
Никогда не следует писать код, основанный на эквивалентных числовых значениях и True
False
. По возможности следует ограничить использование Boolean
переменных логическими значениями, для которых они предназначены. Если необходимо смешивать Boolean
и числовые значения, убедитесь, что вы понимаете метод преобразования, который вы выбрали.
Преобразование в Visual Basic
При использовании CType
ключевых слов или CBool
ключевых слов преобразования для преобразования числовых типов Boolean
данных в 0 становится False
и все остальные значения становятся True
. При преобразовании Boolean
значений в числовые типы с помощью ключевых слов False
преобразования становится 0 и True
становится -1.
Преобразование в Платформу
Метод ToInt32Convert класса в System пространстве имен преобразуется True
в +1.
Если необходимо преобразовать Boolean
значение в числовой тип данных, будьте внимательны к используемому методу преобразования.
Символьный литерал создает ошибку компилятора
В отсутствие символов типов Visual Basic предполагает типы данных по умолчанию для литерала. Тип по умолчанию для символьного литерала, заключенного в кавычки (" "
) — это String
.
Тип String
данных не расширяется до типа данных Char. Это означает, что если вы хотите назначить литерал переменной Char
, необходимо либо выполнить сужение преобразования, либо принудительно применить литерал к типу Char
.
Создание литерала Char для назначения переменной или константе |
---|
1. Объявите переменную или константу как Char .2. Заключите значение символа в кавычки ( " " ).3. Выполните закрывающий двойный кавычки символом литерального типа C , чтобы принудительно выполнить литерал Char . Это необходимо, если параметр проверки типа (option Strict Statement) имеет значение On , и желательно в любом случае. |
В следующем примере показаны неудачные и успешные назначения литерала переменной Char
.
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")
Всегда существует риск использования сужающихся преобразований, так как они могут завершиться сбоем во время выполнения. Например, преобразование может String
Char
завершиться ошибкой, если String
значение содержит несколько символов. Поэтому лучше программировать для использования символа C
типа.
Сбой преобразования строк во время выполнения
Тип данных строки участвует в очень немногих преобразованиях расширения.
String
расширяется только для себя, Object
а только Char
Char
Char()
(массив) расширяется до .String
Это связано с тем, что String
переменные и константы могут содержать значения, которые не могут содержать другие типы данных.
Если параметр проверки типа (Option Strict Statement) имеет значение On
, компилятор запрещает все неявные сужающие преобразования. Это включает в себя тех, кто участвует String
. Код по-прежнему может использовать ключевые слова преобразования, такие как CStr
оператор CType, который направляет платформу .NET Framework на попытку преобразования.
Замечание
Ошибка сужения преобразования подавляется для преобразования элементов в For Each…Next
коллекцию в переменную элемента управления циклом. Дополнительные сведения и примеры см. в разделе "Сужение преобразований" в разделе "Для каждого... Следующая инструкция.
Сужение защиты преобразования
Недостатком сужающих преобразований является то, что они могут завершиться сбоем во время выполнения. Например, если String
переменная содержит что-либо, отличное от "True" или "False", оно не может быть преобразовано в Boolean
. Если он содержит знаки препинания, преобразование в любой числовой тип завершается ошибкой. Если вы не знаете, что String
переменная всегда содержит значения, которые может принимать тип назначения, не следует пытаться преобразовать.
Если необходимо преобразовать из String
другого типа данных, самая безопасная процедура заключается в том, чтобы заключить попытку преобразования в try... Ловить... Наконец, оператор. Это позволяет справиться с ошибкой во время выполнения.
Массивы символов
Один Char
и массив Char
элементов, которые расширяются до String
. Тем не менее, String
не расширяется до Char()
. Чтобы преобразовать String
значение в Char
массив, можно использовать ToCharArray метод System.String класса.
Бессмысленные значения
Как правило, String
значения не имеют смысла в других типах данных, а преобразование является очень искусственным и опасным. По возможности следует ограничить использование String
переменных последовательности символов, для которых они предназначены. Никогда не следует писать код, основанный на эквивалентных значениях в других типах.