2016-03-28 2 views
9

Есть функция, которая возвращает +1 для положительных чисел и -1 для негативов в Swift?Функция «знак» в Swift

Я просмотрел файл огромный, который отображается, если вы щелкните правой кнопкой мыши-> определения на типичной функции, но если он там, я не знаю, что это имя.

Я сделал это:

(num < 0 ? -1 : 1) 

Но я предпочел бы использовать встроенную функцию, если есть - для самостоятельного документирования причин в минимуме.

+0

Так что интересно было то, что я * не * сходит с ума, есть на самом деле не что-нибудь * точно *, как это. Очень неожиданно. –

ответ

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, как в примере, в вашем вопросе).


(Edit в отношении Вашего комментария ниже)

Альтернативное решение выше было бы определить свой собственный протокол с реализацией по умолчанию 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) 
+0

Я думаю, что расширение - это, в конечном счете, путь, я просто совершенно удивлен, что такого еще не существует! В любом случае, есть ли способ использовать дженерики для этого? Или числовые типы являются частью этих «кластеров», которые не являются общими? –

+0

@MauryMarkowitz Даже пользовательский глобальный знак (arg: T) 'должен включать ограничение типа на' T' для протокола, который отображает меньше функции '<', а также инициализацию, чтобы оценить значение считать «ноль». Кроме того, нам нужно будет расширить все типы, которые мы хотим разрешить использовать эту функцию для этого самого протокола, что будет означать некоторые количества кода для всех типов типов Swift: s. В этом случае я думаю, что использование расширения на 'IntegerType' и' FloatingPointType' (как указано выше) является менее болезненным вариантом. Однако я приведу пример использования этого подхода. – dfri

4

Использование:

let result = signbit(number) 

Это возвращает 1 для отрицательных чисел и 0 для положительных результатов.

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

1 

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

0 
+0

это вернет 0 или 1, не так ли? –

+0

да, 1 для негативов, 0 для положительных значений – Masih

+0

Обратите внимание, что это использует бит знака для чисел, представленных шаблоном с плавающей точкой, и, следовательно, работает только для типа с плавающей точкой. Для тестирования знака слова integer вам нужно сначала нажать «Double», прежде чем применять этот метод. – dfri

1

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) 
+0

'0.signValue' должно, вероятно, вернуться' 0' – Clashsoft

+1

Вполне возможно, хотя я думаю, это зависит от вашего конкретного варианта использования. Я выполнял поведение, соответствующее его примеру, показанному выше. – Kevin

1

Поскольку copysign не может быть использован в течение Integer Я использую это расширение:

extension Comparable where Self: SignedNumber { 

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

simd библиотека имеет метод знак:

import simd 

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

Вы получаете simd бесплатно, если вы import SpriteKit.

4

В Swift-4 поплавки имеют новое свойство:

public var sign: FloatingPointSign { get } 
+0

yay! кажется как без проблем ... –

+0

we heart Swift4 – Fattie

Смежные вопросы