2016-03-28 9 views
9

Esiste una funzione che restituisce +1 per i numeri positivi e -1 per i negativi in ​​Swift?Funzione "segno" in Swift

Ho esaminato il file enorme che viene visualizzato se si fa clic con il pulsante destro del mouse su una funzione tipica, ma se è presente non conosco il suo nome.

ho fatto questo:

(num < 0 ? -1 : 1) 

ma io preferisco utilizzare una funzione built-in se non v'è alcuna - per motivi di auto-documentazione al minimo.

+0

Così che cosa è interessante è che io * non è stato * impazzire, non c'è davvero nulla * esattamente * come questo. Molto sorprendente. –

risposta

3

W.r.t. funzioni built-in, penso che il più vicino si ottiene è il metodo di Foundationcopysign(_: Double, _: Double) -> Double

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

Naturalmente necessitano di qualche tipo di conversione nel caso in cui non si sta operando su un numero di tipo Double.

Tuttavia, non vedo alcun motivo per non creare la propria estensione adatta alle proprie esigenze, in particolare per una semplice funzione come sign in quanto non è necessario gonfiarsi, ad es.

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

(qui cedendo 1 anche per 0, come nell'esempio in questione).


(Edit per quanto riguarda il vostro commento qui sotto)

Una soluzione alternativa a quanto sopra potrebbe essere quella di definire il proprio protocollo con un'implementazione di default di sign(), in modo che tutti i tipi conformi a questo protocollo avrebbe accesso a quel metodo 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) 
+0

Penso che l'estensione sia in definitiva la strada da percorrere, sono solo del tutto sorpresa che una cosa del genere non esista già! In ogni caso, c'è un modo per usare i generici per questo? Oppure i tipi numerici fanno parte di quei "cluster" che non sono veramente generici? –

+0

@MauryMarkowitz Anche un 'segno globale personalizzato (arg: T)' dovrebbe includere un vincolo di tipo su 'T' per un protocollo che blueprints meno della funzione' <'così come l'inizializzazione per valutare noi considerare come "zero". Inoltre, avremmo bisogno di estendere tutti i tipi che vogliamo permettere di usare questa funzione allo stesso protocollo, il che significherebbe alcune quantità di codice per tutti i diversi tipi di int di Swift. In questo caso, penso che l'utilizzo di un'estensione su 'IntegerType' e' FloatingPointType' (come sopra) sia un'opzione meno dolorosa. Includerò, tuttavia, un esempio utilizzando l'approccio. – dfri

4

Usa:

let result = signbit(number) 

Ciò restituirà 1 per i numeri negativi e 0 per i positivi.

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

1 

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

0 
+0

questo restituirebbe 0 o 1 non sarebbe? –

+0

sì, 1 per i negativi, 0 per i positivi – Masih

+0

Si noti che questo utilizza il bit di segno per i numeri rappresentati dal modello a virgola mobile, e quindi funziona solo per il tipo di punti mobili. Per testare il segno di dire un intero, è necessario eseguire il cast in 'Double' prima, prima di applicare questo metodo. – dfri

1

FloatingPointType ha un built-in variabile calcolata ma restituisce un valore booleano. Se avete solo bisogno di questa operazione su carri è possibile utilizzare una prolunga in questo modo:

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

Tuttavia, credo che l'approccio migliore sarebbe quella di estendere il protocollo SignedNumberType.

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

Se desideri 0 per tornare -1 poi basta cambiare >=->.

Casi di test:

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

'0.signValue' dovrebbe restituire' 0' – Clashsoft

+1

Molto probabilmente, anche se immagino dipenda dal tuo caso d'uso specifico. Stavo implementando il comportamento coerente con il suo esempio mostrato sopra. – Kevin

1

Dal copysign non può essere utilizzato più di Integer sto usando questa estensione:

extension Comparable where Self: SignedNumber { 

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

La biblioteca simd ha un metodo segno:

import simd 

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

È possibile ottenere simd gratuitamente se si import SpriteKit.

4

In Swift-4 carri hanno una nuova proprietà:

public var sign: FloatingPointSign { get } 
+0

yay! sembra un gioco da ragazzi ... –

+0

we heart Swift4 – Fattie