부동 소수점 타입은 5.5, 100.0 또는 3.141592와 같은 소수를 나타내는데 사용됩니다. 각 부동 소수점 타입에는 고유 한 가능한 범위와 정밀도(precision)가 있습니다. 표준 라이브러리의 부동 소수점 타입은 사용 가능한 경우 Float, Double 및 Float80입니다.
정수 또는 부동 소수점 리터럴을 사용하여 부동 소수점 타입의 새 인스턴스를 만듭니다.
이렇게요.
FloatingPoint프로토콜은 일반적인 산술 연산을 선언하므로, 모든 부동소수점 타입에서 작동하는 함수와 알고리즘을 작성 할 수 있습니다.
다음 예제에서는 직각 삼각형의 빗변 길이를 계산하는 함수를 선언합니다. hypotenuse (_ : _ :) 함수는 FloatingPoint 프로토콜에 제약 된 일반 매개 변수를 사용하기 때문에 부동 소수점 유형을 사용하여 호출 할 수 있습니다.
funchypotenuse<T: FloatingPoint>(_ a: T, _ b: T) -> T {
return (a * a + b * b).squareRoot()
}
let (dx, dy) = (3.0, 4.0)
letdistance = hypotenuse(dx, dy)
// distance == 5.0
Generic에서 배웠죠? T가 궁금하시다면, Generic글을 참고해주세요 :)
이렇게 되면, 저 hypotenuse함수는 FloatingPoint프로토콜을 준수하는 것들만이 파라미터로 들어갈 수 있겠죠.
부동 소수점 값은 부호 및 크기(magnitude)로 표시되며, 크기는 타입의 radix와 인스턴스의 significand 및 지수(exponent)를 사용하여 계산됩니다.
이 크기 계산은 F 유형의 부동 소수점 값 x에 대해 다음 형식을 취합니다. 여기서 **는 지수입니다.
특정 숫자를 나타내는 것 이외에도, 부동 소수점 타입에는 오버플로 및 숫자가 아닌 계산결과로 작업하기 위한 특별한 값이 있습니다.
● Infinity
크기가 너무 커서 표현 가능한 범위 밖으로 값이 반올림되는 값은 반올림되어 무한대(Infinity)로 됩니다.
타입 F에 대하여, 양의 무한대는 각각 F.infinity 및 음의 무한대는 각각 -F.infinity로 표현됩니다.
양의 무한대는 모든 유한한 값과 음의 무한대보다 큽니다. 반면 음의 무한대는 모든 유한한 값과 양의 무한대보다 작습니다.
동일한 부호를 갖는 무한값은 서로 동일합니다.
let values: [Double] = [10.0, 25.0, -10.0, .infinity, -.infinity]
print(values.sorted())
// Prints "[-inf, -10.0, 10.0, 25.0, inf]"
무한 값의 연산은 가능한 한 실제 산술 연산을 따릅니다. 유한 값을 더하거나 빼거나, 무한대를 0이 아닌 유한한 값으로 곱하거나 나누면 결과는 무한대가 됩니다.
● NaN (“not a number”)
부동 소수점 타입은 "숫자가 아닌(not a number)"의 약자인 NaN과 같이 유한한 수나 무한대가 아닌 값을 나타냅니다.
NaN을 다른 값과 비교하면 결과가 false가 됩니다.
let myNaN = Double.nan
print(myNaN > 0)
// Prints "false"print(myNaN < 0)
// Prints "false"print(myNaN == .nan)
// Prints "false"
마지막줄이 이해가 안갈 수도 있죠. myNaN은 분명 Doble의 nan인데, 왜 false가 나오지? true아냐?
아닙니다.
NaN을 다른값과 비교하면, 다른 NaN을 포함하여 결과가 false로 됩니다.
하나의 NaN이 다른 NaN과 동일한지 여부를 테스트하면 false가 되므로, isNaN프로퍼티를 사용하여 값이 NaN인지 테스트합니다.
print(myNaN.isNaN)
// Prints "true"
NaN은 많은 산술 연산을 통해 전파(propagates)됩니다. 많은 값으로 조작하고 있는 경우, NaN의 조작으로 값이 전송되기 때문에, 실행시의 에러는 발생하지 않습니다. 그렇기 때문에 이 동작은 중요합니다. 다음 예제에서는 NaN값이 다른 컨텍스트에서 작동하는 방식을 보여줍니다.
let temperatureData = ["21.5", "19.25", "27", "no data", "28.25", "no data", "23"]
let tempsCelsius = temperatureData.map { Double($0) ?? .nan }
// tempsCelsius == [21.5, 19.25, 27, nan, 28.25, nan, 23.0]
temperatureData 배열의 일부 요소는 유효한 숫자가 아닙니다. 이러한 유효하지 않은 문자열이 Double fiable 이니셜 라이저에 의해 파싱되면이 예에서는 nil-coalescing 연산자 (??)를 사용하여 폴백 값으로 NaN을 제공합니다.
대신에 특정 수치 결과를 얻고, 연산이 필요하면 isNaN프로퍼티를 이용하여 NaN값을 필터링 하십시오.
let validTemps = tempsFahrenheit.filter { !$0.isNaN }
let average = validTemps.reduce(0.0, combine: +) / Double(validTemps.count)
솔직히 이까지 읽으면..이게 왜...싶죠..
이 FloatingPoint의 인스턴스 프로퍼티는 정말정말 많은데..정말 재밌어요. 인스턴스 프로퍼티는 별로 큰 재미는 없ㅈ디만...저는 이 FloatingPoint의 인스턴스 메소드가 알아놓으면 조금 재밌을 것 같아서 이 FloatingPoint를 공부하는 거에요 :)
일단 인스턴스 프로퍼티부터 해봅시다.
FloatingPoint - Instance Property
● exponent : The exponent of the floating-point value.
이렇게나 많은 Case들이 존재합니다. 간단한거니까 하나하나 보진 않을게요. 정말 설명이 다인..그런 것들이라.
● isCanonical
인스턴스의 표현이 표준 형식인지 여부를 나타내는 부울 값입니다.
말그대로 isCanonical입니다. 너 표준이니?
모든 Float 또는 Double 값은 표준이지만 Float80 타입의 비표준(noncanonical) 값이 존재하며 비표준 값이 FloatingPoint 프로토콜을 준수하는 다른 타입에 대해 존재할 수 있습니다.
음..사실 이건 뭐...딱히..정말 쓸 것 같지 않은 그런 프로퍼티...Float80이라고 전부 비표준이 아니라, Float80안에 비표준 값이 있을 수 있다는 거에요! 해당 Float80에 대해 isCanonical을 호출하면 false가 나오겠죠?
뭐가 false인지는 모르겠음ㅎ
● isFinite
이 인스턴스가 유한한지 여부를 나타내는 Bool 값.
NaN 및 무한대 이외의 모든 값은 normal, subnormal에 관계없이 유한 값으로 간주됩니다.
● isInfinite
인스턴스가 무한인지 여부를 나타내는 Bool 값.
isFinite와 isInfinite는 total이 아니기 때문에 이분법(dichotomy)을 형성하지 않습니다. x가 NaN이면 두 속성이 모두 거짓입니다.
● isNaN
인스턴스가 NaN ( "숫자가 아님")인지 여부를 나타내는 Bool 값.
NaN은 NaN을 비롯한 어떤 값과도 같지 않으므로 equal-to 연산자 (==) 또는 not-equal-to 연산자 (! =) 대신 이 프로퍼티를 사용하여 값이 NaN인지 여부를 테스트합니다.
let x = 0.0let y = x * .infinity
// y is a NaN// Comparing with the equal-to operator never returns 'true'print(x == Double.nan)
// Prints "false"print(y == Double.nan)
// Prints "false"// Test with the 'isNaN' property insteadprint(x.isNaN)
// Prints "false"print(y.isNaN)
// Prints "true"
이 프로퍼티(isNaN)은 quiet NaN 및 signaling NaN 모두에 적용됩니다.
Signaling NaN은 일반적으로 일반적인 컴퓨팅 연산에서 사용되면 Invalid 플래그를 발생시킵니다.
● isSubnormal
인스턴스가 subnormal인지 여부를 나타내는 Bool값.
subnormal(비정규)값은 가장 작은 일반적은 숫자보다 작은 크기의 0이 아닌 숫자입니다.(뭐라는건지...A subnormal value is a nonzero number that has a lesser magnitude than the smallest normal number.)
subnorma값은 타입 값에 사용 할 수 있는 전체 정밀도를 사용하지 않습니다. 0은 normal 또는 subnormal인 숫자가 아닙니다. subnorma은 종종 denormal또는 denormalized라고도 합니다. 이들은 동일한 개념의 다른 이름입니다.(어쩐지 subnormal쳤는데 denormal이 나오더라..)
● isZero
이름부터 넘나 쉬운것
인스턴스가 0인지 여부를 나타내는 Bool 값.
isZero 프로퍼티 값이 -0.0 또는 +0.0을 나타내는 경우 true입니다. x.isZero는 다음 비교와 같습니다. x == 0.0.
let x = -0.0
x.isZero // true
x == 0.0// true
● nextDown
드디어 is~가 끝났습니다...이번부터는 조금 헷갈릴 수 있는 개념들이 나와요..!
이 값보다 작은 나타낼 수 있는(representable) 값 중에서 가장 큰 값.
도댜ㅐ체......뭔말..
어떤 유한(finite) 값 x에 대해서 x.nextDown은 x보다 작습니다. nan 또는 -infinity의 경우 x.nextDown은 x 자체입니다. 다음 특수 사례도 적용됩니다.
If x is infinity, then x.nextDown is greatestFiniteMagnitude.
If x is leastNonzeroMagnitude, then x.nextDown is 0.0.
If x is zero, then x.nextDown is -leastNonzeroMagnitude.
If x is -greatestFiniteMagnitude, then x.nextDown is -infinity.
greatestFiniteMagnitude랑 leastNonzeroMagnitude이런게 지금 나오다니...일단 FloatingPoint의 타입 프로퍼티입니다...
아무튼 저도 이 nextDown을 왜 쓰는지 모르겠는데요...
바로 이런것....
a에 3.1의 nextDown해서 넣었지만..
a는 출력은 3.1...
하지만 저 위 코드에서 3.1와 a를 비교했을 때는 false로 나왔으니 확실히 3.1은 아닌 것을 알 수 있어요.
nextDown이니까 3.1보다 작겠죠?
오..실험해보니까
a는 사ㅏㅏ실은 3.09지만 나올때는 3.1로 나오네요.
암튼 다름!!!!
● nextUp
nextDown이 있으면..nextUp도..있는 법......
뭔지는 감이 오시죠?
딱딱한 정의부터 봅시다.
The least representable value that compares greater than this value. 한글로 쓰니까 더 헷갈리실 것 같아서 걍 영어로..쓰겠습니다.
임의의 유한(finite) 값 x에 대하여, x.nextUp는 x보다 큽니다. nan 또는 무한대의 경우 x.nextUp는 x 자체입니다. 다음 특수 사례도 적용됩니다.
If x is -infinity, then x.nextUp is -greatestFiniteMagnitude.
If x is -leastNonzeroMagnitude, then x.nextUp is -0.0.
If x is zero, then x.nextUp is leastNonzeroMagnitude.
If x is greatestFiniteMagnitude, then x.nextUp is infinity.
이제는 a가 3.1보다 커졌습니다~.~
● sign
부동 소수점 값의 부호입니다.
값의 부호가 설정되면 sign 프로퍼티는 .minus이고, 그렇지 않으면 .plus입니다.
let x = -33.375
// x.sign == .minus
이 프로퍼티를 사용하여 부동 소수점 값이 음수인지 여부를 확인하지 마십시오. 값 x의 경우, x.sign == .minus는 반드시 x <0과 같을 필요는 없습니다. 특히 x.sign == .minus는 x가 -0이고 x < 0이면 x는 항상 false입니다. x가 NaN이면 x.sign은 .plus 또는 .minus가 될 수 있습니다.
● significand
부동 소수점 값의 유효 숫자입니다.
let magnitude = x.significand * F.radix ** x.exponent
위에서 했죠?
구하는 방법도...
저 1.34375가 바로 significand입니다.
If x is zero, then x.significand is 0.0. // x가 0이면, x의 significand는 0.0입니다.
If x is infinity, then x.significand is 1.0.//x가 infinity이면, x의 significand는 1.0입니다.
If x is NaN, then x.significand is NaN.//x가 NaN이면, x의 significand는 NaN입니다.
● ulp
이 값의 마지막 자리에있는 단위(unit)입니다.
이 값의 significand에서 최하위 숫자의 단위(unit)입니다. 대부분의 수 x에 대해, 이것은 x와 그 다음으로 큰 (크기로) 표현 가능한 수 사이의 차이입니다. 알고 있어야 할 몇 가지 중요한 경우가 있습니다.
- x가 유한한 수(finite)가 아닌 경우 x.ulp는 NaN입니다.
- x의 크기가 매우 작으면 x.ulp가 비정규(subnormal) 숫자 일 수 있습니다. 타입이 subnormals을 지원하지 않으면 x.ulp가 0으로 반올림 될 수 있습니다.
- greaterFiniteMagnitude.ulp는 더 큰 다음 값이 무한대 임에도 불구하고 유한수입니다.
이 quantity 또는 related quantity은 종종 epsilon(엡실론) 는 machine epsilon이라고합니다. 그 이름은 다른 언어로 다른 의미를 지니고 있기 때문에 혼동을 야기 할 수 있으며 비교를 위해 사용하는 것은 좋게 허용(tolerance, 허용오차)되지만, 거의 그렇지 않습니다.
이건.....진짜..무슨소리인지 모르겠네요 ㅎㅎ
이렇게 FloatingPoint의 인스턴스 프로퍼티가 끝났습니다..
일단 너무 길어지니까 여기까지...시간 되면 꼭 메소드들 쓸게요!!! 타입 프로퍼티가 남긴 했지만..