데이터 형식 문제 해결(Visual Basic)
이 페이지에서는 내장 데이터 형식에 대한 작업을 수행할 때 발생할 수 있는 일반적인 문제를 보여 줍니다.
동일한 것으로 간주되지 않는 부동 소수점 식
부동 소수점 숫자(Single 데이터 형식(Visual Basic) 및 Double 데이터 형식(Visual Basic))로 작업하는 경우 숫자는 이진 소수로 저장됩니다.즉, 부동 소수점 숫자는 이진 소수(k / (2 ^ n) 형식, 여기서 k 및 n은 정수임)가 아닌 정확한 수량으로 표시될 수 없습니다.예를 들어, 0.5(= 1/2)와 0.3125(= 5/16)는 정밀한 값이지만 0.2(= 1/5)와 0.3(= 3/10)은 근사값입니다.
이러한 부정확성으로 인해 부동 소수점 값으로 작업할 때 정확한 결과를 사용할 수 없습니다.특히, 이론적으로 동일한 두 값이 약간 다르게 표시될 수 있습니다.
부동 소수점 수량을 비교하려면 |
다음 예제에서는 두 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 메서드를 사용하므로 CStr 키워드를 사용할 때보다 더 정확하게 지정할 수 있습니다.기본값은 15자리지만 "G17" 형식에서는 기본값이 17자리로 확대됩니다.
정확한 결과를 반환하지 않는 Mod 연산자
부동 소수점 저장의 부정확성으로 인해 Mod 연산자(Visual Basic)는 하나 이상의 피연산자가 부동 소수점인 경우 예기치 않은 결과를 반환할 수 있습니다.
Decimal 데이터 형식(Visual Basic)은 부동 소수점 표현을 사용하지 않습니다.Single 및 Double에서는 정확하지 않는 숫자가 Decimal에서는 정확하게 표시되는 경우가 있습니다(예: 0.2, 0.3).Decimal에서는 부동 소수점에서보다 산술 연산이 더 느리지만 더 정확한 결과가 나타나므로 성능 감소를 감내할 만한 가치가 있습니다.
부동 소수점 수량의 정수 나머지를 찾으려면 |
|
다음 예제에서는 부동 소수점 피연산자의 잠재적인 부정확성에 대해 설명합니다.
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 메서드를 사용하므로 CStr 키워드를 사용할 때보다 더 정확하게 지정할 수 있습니다.기본값은 15자리지만 "G17" 형식에서는 기본값이 17자리로 확대됩니다.
zeroPointTwo는 Double이므로 0.2에 대한 값은 무한 반복되는 이진 소수이며 저장된 값은 0.20000000000000001입니다.2.0을 이 수로 나누면 몫이 9.9999999999999995이고 나머지는 0.19999999999999991입니다.
decimalRemainder에 대한 식에서 D 리터럴 형식 문자는 Decimal에 두 피연산자를 모두 적용하므로 0.2로 정확하게 표시됩니다.따라서 Mod 연산자는 예상한 나머지 0.0을 반환합니다.
decimalRemainder를 Decimal로 선언하는 것만으로는 충분하지 않습니다.리터럴을 Decimal에 적용하거나 Double을 기본값으로 사용하여 decimalRemainder가 doubleRemainder와 동일한 정확도의 값을 받아야 합니다.
숫자 형식으로 정확하게 변환되지 않는 부울 형식
Boolean 데이터 형식(Visual Basic) 값은 숫자로 저장되지 않고 저장된 값은 숫자가 아닙니다.이전 버전과의 호환성을 위해 Visual Basic에서는 Boolean 형식과 숫자 형식 간에 변환할 수 있도록 변환 키워드(CType 함수(Visual Basic), CBool, CInt 등)를 제공합니다..NET Framework 메서드를 수행할 때처럼 이러한 변환은 언어마다 다르게 수행될 수 있습니다.
True와 False를 숫자 값으로 나타내도록 코드를 작성하지 마십시오.Boolean 변수에는 가능하면 원래 용도에 맞는 논리 값이 사용되도록 제한해야 합니다.Boolean과 숫자 값을 혼합해야 하는 경우에는 선택한 변환 메서드를 알고 있어야 합니다.
변환(Visual Basic)
CType 또는 CBool 변환 키워드를 사용하여 숫자 데이터 형식을 Boolean으로 변환하는 경우 0은 False가 되고 다른 모든 값은 True가 됩니다.변환 키워드를 사용하여 Boolean 값을 숫자 형식으로 변환하는 경우 False는 0이 되고 True는 -1이 됩니다.
변환(Framework)
System 네임스페이스에서 Convert 클래스의 ToInt32 메서드는 True를 +1로 변환합니다.
Boolean 값을 숫자 데이터 형식으로 변환해야 하는 경우 변환 메서드를 주의하여 사용하십시오.
컴파일러 오류를 생성하는 문자 리터럴
Visual Basic에서는 형식 문자가 없는 경우 리터럴에 대한 기본 데이터 형식을 사용합니다.큰따옴표(" ")로 묶인 문자 리터럴의 기본 형식은 String입니다.
String 데이터 형식은 Char 데이터 형식(Visual Basic)으로 확대 변환되지 않습니다.즉, 리터럴을 Char 변수에 할당하려면 축소 변환을 사용하거나 리터럴을 Char 형식에 적용해야 합니다.
문자 리터럴을 만들어 변수 또는 상수에 할당하려면 |
|
다음 예제에서는 리터럴을 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 데이터 형식(Visual Basic)은 확대 변환에 거의 사용되지 않습니다.String은 문자열 자체와 Object로만 확대 변환되고 Char 및 Char()(Char 배열)만 String으로 확대 변환됩니다.이는 String 변수와 상수에 다른 데이터 형식에서 사용할 수 없는 값이 포함될 수 있기 때문입니다.
형식 검사 스위치(Option Strict 문)가 On인 경우 컴파일러에서는 모든 암시적 축소 변환을 허용하지 않습니다.여기에는 String을 포함하는 변환도 포함됩니다.이 경우에도 코드에서는 CStr 및 CType 함수(Visual Basic)와 같은 변환 키워드를 사용하여 .NET Framework에게 변환 시도를 지시할 수 있습니다.
[!참고]
For Each…Next 컬렉션의 요소에서 루프 제어 변수로의 변환에 대한 축소 변환 오류는 표시되지 않습니다.자세한 내용 및 예제는 For Each...Next 문(Visual Basic)의 "축소 변환" 단원을 참조하십시오.
축소 변환 보호
축소 변환 시 런타임에 실패할 수 있습니다.예를 들어, "True" 또는 "False" 이외의 값을 포함하는 String 변수는 Boolean으로 변환될 수 없으며구두점 문자를 포함하는 String 변수는 숫자 형식으로 변환되지 않습니다.String 변수가 대상 형식에 사용할 수 있는 값만 포함하는지 확실히 알 수 없다면 변환을 시도하지 마십시오.
String에서 다른 데이터 형식으로 변환해야 하는 경우에는 시도된 변환을 Try...Catch...Finally 문(Visual Basic)으로 묶는 것이 가장 안전합니다.이렇게 하면 런타임 실패를 직접 처리할 수 있습니다.
문자 배열
단일 Char와 Char 요소 배열은 모두 String으로 확대 변환되지만String은 Char()로 확대 변환되지 않습니다.String 값을 Char 배열로 변환하려면 System.String 클래스의 ToCharArray 메서드를 사용합니다.
의미 없는 값
일반적으로 String 값은 다른 데이터 형식에서는 의미가 없으므로 이를 변환하는 것은 매우 부적절하며 위험합니다.가능하면 String 변수는 이 변수를 사용하도록 디자인된 문자 시퀀스에서만 사용하도록 합니다.해당 값을 다른 형식으로 사용하는 코드를 작성하지 마십시오.