當前位置: 首頁>>編程示例 >>用法及示例精選 >>正文


Swift FloatingPoint用法及代碼示例

協議

FloatingPoint

浮點數值類型。

聲明

protocol FloatingPoint : Hashable, SignedNumeric, Strideable where Self == Self.Magnitude

概述

浮點類型用於表示小數,如 5.5、100.0 或 3.14159274。每種浮點類型都有自己可能的範圍和精度。標準庫中的浮點類型是 FloatDoubleFloat80 (如果可用)。

使用整數或浮點文字創建浮點類型的新實例。例如:


let temperature = 33.2
let recordHigh = 37.5

FloatingPoint 協議聲明了常見的算術運算,因此您可以編寫適用於任何浮點類型的函數和算法。下麵的示例聲明了一個函數,該函數在給定兩個垂直邊的情況下計算直角三角形的斜邊長度。因為hypotenuse(_:_:) 函數使用受FloatingPoint 協議約束的泛型參數,所以可以使用任何浮點類型調用它。


func hypotenuse<T: FloatingPoint>(_ a: T, _ b: T) -> T {
    return (a * a + b * b).squareRoot()
}


let (dx, dy) = (3.0, 4.0)
let distance = hypotenuse(dx, dy)
// distance == 5.0

浮點值表示為 signmagnitude ,其中大小是使用類型的 radix 和實例的 significandexponent 計算的。對於 F 類型的浮點值 x,此幅度計算采用以下形式,其中 ** 是冪:


x.significand * F.radix ** x.exponent

這是一個數字 -8.5 的示例,表示為 Double 類型的實例,它定義了 2 的基數。


let y = -8.5
// y.sign == .minus
// y.significand == 1.0625
// y.exponent == 3


let magnitude = 1.0625 * Double(2 ** 3)
// magnitude == 8.5

符合 FloatingPoint 協議的類型提供了 IEEE 754 specification 的最基本(第 5 條)操作。該協議不以任何方式固定基數、精度和指數範圍,但它強製執行任何 IEEE 754 浮點類型的基本要求。

其他注意事項

除了表示特定數字外,浮點類型還具有用於處理溢出和非數字計算結果的特殊值。

無窮

任何幅度如此之大以至於會舍入到可表示數字範圍之外的值的任何值都將舍入為 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]"

具有無限值的運算盡可能遵循實數運算:將有限值相加或相減,或將無窮大乘以或除以非零有限值,得到無窮大。

NaN (“not a number”)

浮點類型表示既不是有限數也不是無窮大的值,如 NaN,“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"

因為測試一個 NaN 是否等於另一個 NaN 會導致 false ,所以使用 isNaN 屬性來測試一個值是否為 NaN。


print(myNaN.isNaN)
// Prints "true"

NaN 通過許多算術運算傳播。當您對多個值進行操作時,此行為很有值,因為對 NaN 的操作隻是轉發值並且不會導致運行時錯誤。以下示例顯示NaN 值如何在不同的上下文中運行。

假設您有一組溫度數據,您需要為其報告一些一般統計數據:觀測總數、有效觀測數和平均溫度。首先,將一組攝氏溫度的觀察值從字符串解析為 Double 值:


let temperatureData = ["21.5", "19.25", "27", "no data", "28.25", "no data", "23"]
let tempsCelsius = temperatureData.map { Double($0) ?? .nan }
print(tempsCelsius)
// Prints "[21.5, 19.25, 27, nan, 28.25, nan, 23.0]"

請注意,temperatureData 數組中的某些元素不是有效數字。當 Double 可失敗初始化程序解析這些無效字符串時,該示例使用 nil-coalescing 運算符 (??) 提供 NaN 作為後備值。

接下來,將攝氏溫度轉換為華氏溫度:


let tempsFahrenheit = tempsCelsius.map { $0 * 1.8 + 32 }
print(tempsFahrenheit)
// Prints "[70.7, 66.65, 80.6, nan, 82.85, nan, 73.4]"

tempsCelsius 數組中的 NaN 值通過轉換傳播並在 tempsFahrenheit 中保持 NaN 。

因為計算觀測值的平均值涉及組合 tempsFahrenheit 數組的每個值,所以任何 NaN 值都會導致結果也為 NaN,如下例所示:


let badAverage = tempsFahrenheit.reduce(0.0, +) / Double(tempsFahrenheit.count)
// badAverage.isNaN == true

相反,當您需要一個運算來獲得特定的數值結果時,請使用 isNaN 屬性過濾掉任何 NaN 值。


let validTemps = tempsFahrenheit.filter { !$0.isNaN }
let average = validTemps.reduce(0.0, +) / Double(validTemps.count)

最後,報告平均溫度和觀測計數:


print("Average: \(average)°F in \(validTemps.count) " +
      "out of \(tempsFahrenheit.count) observations.")
// Prints "Average: 74.84°F in 5 out of 7 observations."

可用版本

iOS 8.0+, iPadOS 8.0+, macOS 10.10+, Mac Catalyst 13.0+, tvOS 9.0+, watchOS 2.0+

相關用法


注:本文由純淨天空篩選整理自apple.com大神的英文原創作品 FloatingPoint。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。