"sign" function in Swift
Swift 4
As has already been pointed out in @Wil Shipley's Swift 4 answer, there is now a sign
property in the FloatingPoint
protocol:
FloatingPointSign
The sign of a floating-point value.
Enumeration Cases
- case
minus
The sign for a negative value.- case
plus
The sign for a positive value.
However, the comments to the sign
blueprint in the source code of FloatingPoint
contains important information that is (yet?) not present in the generated docs:
/// The sign of the floating-point value. /// /// The `sign` property is `.minus` if the value's signbit is set, and /// `.plus` otherwise. For example: /// /// let x = -33.375 /// // x.sign == .minus /// /// Do not use this property to check whether a floating point value is /// negative. For a value `x`, the comparison `x.sign == .minus` is not /// necessarily the same as `x < 0`. In particular, `x.sign == .minus` if /// `x` is -0, and while `x < 0` is always `false` if `x` is NaN, `x.sign` /// could be either `.plus` or `.minus`.
emphasizing, "... .minus
if the value's signbit is set" and "Do not use this property to check whether a floating point value is negative".
Summa summarum: use the new sign
property of the FloatingPoint
protocol to actually check whether the value's signbit is set or not, but make sure to use some care if attempting to use this property to tell whether a number is negative or not.
var f: Float = 0.0
if case .minus = (-f).sign { print("A. f is negative!") }
f = -Float.nan
if f < 0 { print("B. f is negative!") }
if case .minus = f.sign { print("C. f is negative!") }
// A. f is negative!
// C. f is negative!
Swift 3
W.r.t. built-in functions, I think the closest you'll get is the Foundation
method copysign(_: Double, _: Double) -> Double
let foo = -15.2
let sign = copysign(1.0, foo) // -1.0 (Double)
Naturally needing some type conversion in case you're not operating on a number of type Double
.
However, I see no reason why not to create your own extension fit to your needs, especially for such a simple function as sign
as they needn't get bloated, e.g.
extension IntegerType {
func sign() -> Int {
return (self < 0 ? -1 : 1)
}
/* or, use signature: func sign() -> Self */
}
extension FloatingPointType {
func sign() -> Int {
return (self < Self(0) ? -1 : 1)
}
}
(here yielding 1
also for 0
, as in the example in your question).
(Edit with regard to your comment below)
An alternative solution to the above would be to define your own protocol with a default implementation of sign()
, so that all types conforming to this protocol would have access to that sign()
method.
protocol Signable {
init()
func <(lhs:Self, rhs:Self) -> Bool
}
extension Signable {
func sign() -> Int {
return (self < Self() ? -1 : 1)
}
}
/* extend signed integer types to Signable */
extension Int: Signable { } // already have < and init() functions, OK
extension Int8 : Signable { } // ...
extension Int16 : Signable { }
extension Int32 : Signable { }
extension Int64 : Signable { }
/* extend floating point types to Signable */
extension Double : Signable { }
extension Float : Signable { }
extension CGFloat : Signable { }
/* example usage */
let foo = -4.2
let bar = 42
foo.sign() // -1 (Int)
bar.sign() // 1 (Int)
The simd
library has a sign method:
import simd
sign(-100.0) // returns -1
sign(100.0) // returns 1
sign(0.0) // returns 0
You get simd
for free if you import SpriteKit
.