Swift中的“sign”函数

时间:2016-03-28 22:05:17

标签: swift

是否有一个函数在Swift中为正数返回+1而在负数中返回-1?

我查看了一个典型函数上右键单击>定义时出现的巨大的文件,但是如果它在那里我不知道它的名字。

我这样做了:

(num < 0 ? -1 : 1)

但我宁愿使用内置函数(如果有的话) - 至少是出于自我记录的原因。

7 个答案:

答案 0 :(得分:10)

Swift 4

正如@Wil Shipley's Swift 4 answer中已经指出的那样,现在有一个sign property in the FloatingPoint protocol

  

<强> FloatingPointSign

     

浮点值的符号。

     

枚举案件

     
      
  • 案例minus负值的符号。
  •   
  • case plus正值的符号。
  •   

但是 ,对the sign blueprint in the source code of FloatingPoint的评论包含生成的文档中不存在的重要信息:

/// 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`.

强调,&#34; ... .minus如果设置了&#34;&#34; &#34;请勿使用此属性检查浮点值是否为负值&#34;

Summa summarum:使用sign协议的新FloatingPoint属性来实际检查值的标识是否已设置,但如果尝试使用,请务必小心使用此属性判断数字是否为负数。

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。内置函数,我认为最接近的是Foundation方法copysign(_: Double, _: Double) -> Double

let foo = -15.2
let sign = copysign(1.0, foo) // -1.0 (Double)

如果您未在多种类型Double上操作,则自然需要进行某种类型转换。

但是,我认为没有理由不创建适合您需求的扩展,特别是对于sign这样一个简单的功能,因为它们不会变得臃肿,例如。

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

(此处1也会产生0,如您问题中的示例所示。)

(关于以下评论进行编辑)

上述的替代解决方案是使用默认实现sign()定义您自己的协议,以便符合此协议的所有类型都可以访问该sign()方法。

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)

答案 1 :(得分:7)

在Swift-4花车中有一个新属性:

public var sign: FloatingPointSign { get }

(但是这只会检查符号位,因此在某些情况下会失败,例如-0 - 请参阅上面接受的答案。)

答案 2 :(得分:5)

使用:

let result = signbit(number)

这将为负数返回1,为正数返回0。

let number = -1.0
print("\(signbit(number))")

1

let number = 1.0
print("\(signbit(number))")

0

答案 3 :(得分:5)

simd库有一个签名方法:

import simd

sign(-100.0) // returns -1
sign(100.0) // returns 1
sign(0.0) // returns 0

如果您simd,则免费获得import SpriteKit

答案 4 :(得分:2)

FloatingPointType有一个内置的计算变量,但它返回一个布尔值。如果您只需要对浮点数进行此操作,则可以使用如下扩展名:

extension FloatingPointType {
    var signValue: Int {
        return isSignMinus ? -1 : 1
    }
}

但是,我认为最好的方法是扩展SignedNumberType协议。

extension SignedNumberType {
    var signValue: Int {
        return (self >= -self) ? 1 : -1
    }
}

如果您希望0返回-1,则只需将>=更改为>

测试用例:

print(3.0.signValue)
print(0.signValue)
print(-3.0.signValue)

答案 5 :(得分:1)

由于copysign不能在Integer上使用我使用此扩展程序:

extension Comparable where Self: SignedNumber {

    var sign: Int {
        guard self != -self else {
            return 0
        }
        return self > -self ? 1 : -1
    } 
}

答案 6 :(得分:0)

如果您的值为整数,则可以使用 signum()。

https://developer.apple.com/documentation/swift/int/2886673-signum

这是一个代码片段,以使其清楚;

let negative: Int = -10
let zero: Int = 0
let positive: Int = 10

print(negative.signum()) // prints "-1"
print(zero.signum()) // prints "0"
print(positive.signum()) // prints "1"