다음을 통해 공유


데이터 형식 문제 해결(Visual Basic)

이 페이지에는 내장 데이터 형식에 대한 작업을 수행할 때 발생할 수 있는 몇 가지 일반적인 문제가 나열되어 있습니다.

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

이전 예제에서는 구조체의 메서드를 Double 사용하여 ToString 키워드(keyword) 사용하는 것보다 더 나은 정밀도를 CStr 지정할 수 있습니다. 기본값은 15자리이지만 "G17" 형식은 17자리로 확장됩니다.

Mod 연산자가 정확한 결과를 반환하지 않음

부동 소수점 스토리지의 부정확성으로 인해 Mod 연산자는 피연산자 중 하나 이상이 부동 소수점일 때 예기치 않은 결과를 반환할 수 있습니다.

10진수 데이터 형식은 부동 소수점 표현을 사용하지 않습니다. 에서 정확 Single 하지 DoubleDecimal 않은 많은 숫자(예: 0.2 및 0.3). 산술 연산은 부동 소수점보다 느리 Decimal 지만 더 나은 정밀도를 달성하기 위해 성능이 저하될 수 있습니다.

부동 소수점 수량의 정수 나머지를 찾으려면
1. 변수를 로 Decimal선언합니다.
2. 데이터 형식에 비해 값이 너무 큰 경우 리터럴 형식 문자를 D 사용하여 리터럴 DecimalLong 로 강제 적용합니다.

다음 예제에서는 부동 소수점 피연산자의 잠재적 부정확함을 보여 줍니다.

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

이전 예제에서는 구조체의 메서드를 Double 사용하여 ToString 키워드(keyword) 사용하는 것보다 더 나은 정밀도를 CStr 지정할 수 있습니다. 기본값은 15자리이지만 "G17" 형식은 17자리로 확장됩니다.

Double이므로 zeroPointTwo 0.2의 값은 저장된 값이 0.200000000000000000001인 무한 반복 이진 분수입니다. 2.0을 이 수량으로 나눈 값은 9.999999999999999995의 나머지 0.19999999999999991입니다.

decimalRemainder에서 리터럴 형식 문자 D 는 두 피연산자를 모두 로 강제 적용 Decimal하고 0.2에는 정확한 표현이 있습니다. 따라서 연산자는 Mod 예상되는 나머지 0.0을 생성합니다.

Decimal선언 decimalRemainder 하는 것으로는 충분하지 않습니다. 또한 리터럴을 로 강제 적용 Decimal해야 합니다. 또는 리터럴은 기본적으로 를 사용하고 DoubledecimalRemainder 동일한 부정확한 값을 doubleRemainder받습니다.

부울 형식이 숫자 형식으로 정확하게 변환되지 않음

부울 데이터 형식 값은 숫자로 저장되지 않으며 저장된 값은 숫자와 동일하지 않습니다. 이전 버전과의 호환성을 위해 Visual Basic은 및 숫자 형식 간에 Boolean 변환할 변환 키워드(CType 함수, CBool, CInt등)를 제공합니다. 그러나 다른 언어는 .NET Framework 메서드와 마찬가지로 이러한 변환을 다르게 수행하는 경우가 있습니다.

False에 해당하는 숫자 값을 True 사용하는 코드를 작성해서는 안 됩니다. 가능하면 변수의 Boolean 사용을 디자인된 논리 값으로 제한해야 합니다. 및 숫자 값을 혼합 Boolean 해야 하는 경우 선택한 변환 방법을 이해해야 합니다.

Visual Basic의 변환

또는 변환 키워드를 CType 사용하여 숫자 데이터 형식Boolean을 로 변환하면 0이 되고 False 다른 모든 값은 가 됩니다True.CBool 변환 키워드 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 포함된 경우 에서 로 StringChar 의 변환이 실패할 수 있습니다. 따라서 형식 문자를 사용하는 것이 더 나은 프로그래밍입니다 C .

런타임에 문자열 변환 실패

문자열 데이터 형식은 매우 적은 수의 확대 변환에 참여합니다. String는 자체 및 로만 확대되고 ObjectChar() (배열)만 Char 으로 Char 확장됩니다String. 변수와 상수는 다른 데이터 형식에 포함될 수 없는 값을 포함할 수 있기 String 때문입니다.

형식 검사 스위치(Option Strict 문)가 이면 On컴파일러는 모든 암시적 축소 변환을 허용하지 않습니다. 여기에는 을 포함하는 항목이 포함됩니다 String. 코드는 변환을 시도하도록 .NET Framework 지시하는 CType 함수와 같은 CStr 변환 키워드를 계속 사용할 수 있습니다.

참고

컬렉션의 요소 For Each…Next 에서 루프 제어 변수로의 변환에 대해 축소 변환 오류가 표시되지 않습니다. 자세한 내용과 예제는 For Each...의 "축소 변환" 섹션을 참조 하세요. 다음 문입니다.

축소 변환 보호

변환 축소의 단점은 런타임에 실패할 수 있다는 것입니다. 예를 들어 변수에 String "True" 또는 "False" 이외의 항목이 포함된 경우 로 변환 Boolean할 수 없습니다. 문장 부호 문자가 포함된 경우 숫자 형식으로 변환하지 못합니다. 변수에 항상 대상 형식이 String 허용할 수 있는 값이 있다는 것을 알지 못하면 변환을 시도해서는 안 됩니다.

에서 String 다른 데이터 형식으로 변환해야 하는 경우 가장 안전한 절차는 Try...에서 시도된 변환을 묶는 것입니다 . 잡을... 마지막으로 문입니다. 이렇게 하면 런타임 실패를 처리할 수 있습니다.

문자 배열

요소의 Char 단일 Char 배열과 배열은 모두 로 확장합니다String. 그러나 은 StringChar()확장되지 않습니다. 값을 Char 배열로 String 변환하려면 클래스의 메서드를 ToCharArraySystem.String 사용할 수 있습니다.

의미 없는 값

일반적으로 String 값은 다른 데이터 형식에서 의미가 없으며 변환은 매우 인공적이고 위험합니다. 가능하면 변수의 String 사용을 디자인된 문자 시퀀스로 제한해야 합니다. 다른 형식에서 동등한 값을 사용하는 코드를 작성해서는 안 됩니다.

추가 정보