이 페이지에는 내장 데이터 형식에 대한 작업을 수행할 때 발생할 수 있는 몇 가지 일반적인 문제가 나열되어 있습니다.
Floating-Point 식이 같음으로 비교되지 않음
부동 소수점 숫자(단일 데이터 형식 및 이중 데이터 형식)를 사용하는 경우 이진 분수로 저장됩니다. 즉, k와 n이 정수인 k/(2 ^ 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 연산자가 정확한 결과를 반환하지 않음
부동 소수점 스토리지의 부정확성으로 인해 Mod 연산자는 피연산자 중 하나 이상이 부동 소수점일 때 예기치 않은 결과를 반환할 수 있습니다.
10진수 데이터 형식은 부동 소수점 표현을 사용하지 않습니다. 정확 SingleDouble 하지 않은 많은 숫자(예: 0.2 및 0.3)입니다 Decimal . 산술 연산은 부동 소수점보다 느리 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자리로 확장됩니다.
Double0.2에 대한 값은 저장된 값이 0.200000000000000001인 무한 반복 이진 분수이기 때문 zeroPointTwo 입니다. 이 수량으로 2.0을 나누면 나머지 0.1999999999999999999999999999991의 나머지와 9.9999999999999999999을 산출합니다.
식 decimalRemainder에서 리터럴 형식 문자 D 는 피연산자를 Decimal모두 강제로 적용하고 0.2에는 정확한 표현이 있습니다. 따라서 연산자는 Mod 0.0의 예상 나머지를 생성합니다.
로 선언 decimalRemainderDecimal하는 것으로는 충분하지 않습니다. 또한 리터럴을 강제로 적용해야 합니다. Decimal또는 리터럴이 기본적으로 사용 Double 되며 decimalRemainder 동일한 부정확한 값을 doubleRemainder받습니다.
부울 형식이 숫자 형식으로 정확하게 변환되지 않음
부울 데이터 형식 값은 숫자로 저장되지 않으며 저장된 값은 숫자와 동일하지 않습니다. 이전 버전과의 호환성을 위해 Visual Basic은 변환 키워드(CType 연산자, CBoolCInt등)를 제공하여 숫자 형식 간에 Boolean 변환합니다. 그러나 다른 언어는 .NET Framework 메서드와 마찬가지로 이러한 변환을 다르게 수행하는 경우도 있습니다.
동등한 숫자 값 True 과 False.에 대한 코드를 작성해서는 안 됩니다. 가능하면 변수의 Boolean 사용을 디자인된 논리 값으로 제한해야 합니다. 값과 숫자 값을 혼합 Boolean 해야 하는 경우 선택한 변환 방법을 이해해야 합니다.
Visual Basic의 변환
또는 CBool 변환 키워드를 사용하여 CType 숫자 데이터 형식을 변환하면 Boolean0이 False 되고 다른 모든 값은 True됩니다. 변환 키워드 False 를 사용하여 값을 숫자 형식으로 변환 Boolean 하면 0이 되고 True -1이 됩니다.
프레임워크의 변환
네임스페이 Convert 스의 클래스 메서드가 ToInt32System +1로 변환됩니다True.
값을 숫자 데이터 형식으로 변환 Boolean 해야 하는 경우 사용하는 변환 방법에 주의해야 합니다.
문자 리터럴에서 컴파일러 오류를 생성합니다.
형식 문자가 없는 경우 Visual Basic은 리터럴에 대한 기본 데이터 형식을 가정합니다. 따옴표(" ")로 묶인 문자 리터럴의 기본 형식은 다음과 같습니다 String.
데이터 형식은 StringChar 데이터 형식으로 확장되지 않습니다. 즉, 변수에 리터럴을 Char 할당하려면 축소 변환을 수행하거나 리터럴을 형식으로 강제 적용 Char 해야 합니다.
| 변수 또는 상수에 할당할 Char 리터럴을 만들려면 |
|---|
1. 변수 또는 상수로 Char선언합니다.2. 문자 값을 따옴표( " ")로 묶습니다.3. 리터럴 형식 문자 C 와 함께 닫는 큰따옴표를 따라 리터럴을 강제 적용합니다 Char. 형식 검사 스위치(Option Strict 문) 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 변환 String 이 실패할 Char 수 있습니다. 따라서 형식 문자를 사용하는 것이 더 나은 프로그래밍입니다 C .
런타임에 문자열 변환 실패
문자열 데이터 형식은 매우 적은 확대 변환에 참여합니다.
String는 그 자체로만 확대되며Object, (배열)Char만 Char()Char 확장됩니다String. 변수와 상수는 다른 데이터 형식에 포함할 수 없는 값을 포함할 수 있기 String 때문입니다.
형식 검사 스위치(Option Strict 문)인 경우 On컴파일러는 모든 암시적 축소 변환을 허용하지 않습니다. 여기에는 관련된 항목이 포함됩니다 String. 코드는 .NET Framework에서 변환을 시도하도록 지시하는 CType 연산자와 같은 CStr 변환 키워드를 계속 사용할 수 있습니다.
비고
컬렉션의 요소 For Each…Next 에서 루프 컨트롤 변수로 변환하는 경우 축소 변환 오류가 표시되지 않습니다. 자세한 내용 및 예제는 For Each...의 "축소 변환" 섹션을 참조하세요. 다음 문입니다.
축소 변환 보호
축소 변환의 단점은 런타임에 실패할 수 있다는 것입니다. 예를 들어 변수에 String "True" 또는 "False" 이외의 항목이 포함되어 있으면 변환 Boolean할 수 없습니다. 문장 부호 문자가 포함된 경우 숫자 형식으로 변환하지 못합니다. 변수에 대상 형식이 String 허용할 수 있는 값이 항상 포함된다는 것을 알지 못하면 변환을 시도해서는 안 됩니다.
다른 데이터 형식으로 String 변환해야 하는 경우 가장 안전한 절차는 Try...에서 시도된 변환을 묶는 것입니다 . 잡기... Finally 문입니다. 이렇게 하면 런타임 오류를 처리할 수 있습니다.
문자 배열
요소의 Char 단일 Char 배열과 배열은 둘 다 .로 확장합니다String. 그러나 .로 String 확장 Char()되지는 않습니다. 값을 배열로 StringChar 변환하려면 클래스의 메서드를 ToCharArraySystem.String 사용할 수 있습니다.
의미 없는 값
일반적으로 String 값은 다른 데이터 형식에서 의미가 없으며 변환은 매우 인공적이고 위험합니다. 가능하면 변수의 String 사용을 디자인된 문자 시퀀스로 제한해야 합니다. 다른 형식에서 동등한 값을 사용하는 코드를 작성해서는 안 됩니다.
참고하십시오
.NET