Округлить CGFloat в Swift
Как я могу округлить CGFloat в Swift?
Я пытался ceil(CDouble(myCGFloat))
но это работает только на iPad Air и iPhone 5S.
при запуске на другом моделируемом устройстве я получаю сообщение об ошибке 'NSNumber' is not a subtype of 'CGFloat'
5 ответов
обновление: Apple теперь определила некоторые CGFloat-специфические версии общих функций, таких как ceil
:
func ceil(x: CGFloat) -> CGFloat
...в частности, чтобы справиться с 32/64-битной разницей. Если вы просто используете ceil
С аргументом CGFloat теперь он должен работать на всех архитектурах.
мой оригинальный ответ:
это довольно ужасно, я думаю, но может ли кто-нибудь придумать лучший способ? #if
кажется, не работает для CGFLOAT_IS_DOUBLE
; Я думаю, вы ограничены в построении конфигурации, от чего я вижу в документации для условной компиляции.
var x = CGFloat(0.5)
#if arch(x86_64) || arch(arm64)
var test = ceil(x)
#else
var test = ceilf(x)
#endif
наиболее правильным синтаксисом, вероятно, будет:
var f: CGFloat = 2.5
var roundedF = CGFloat(ceil(Double(f)))
использовать ceil
Я сначала сделаю CGFloat
a Double
и после потолка, я преобразовать его обратно в CGFloat
.
это работает, когда CGFloat
определяется как CFloat
или CDouble
.
вы также можете определить ceil
для поплавков (это было фактически реализовано в Swift 2):
func ceil(f: CFloat) -> CFloat {
return ceilf(f)
}
тогда вы сможете позвонить прямо
var roundedF: CGFloat = ceil(f)
пока сохраняющ тип безопасность.
Я действительно считаю, что это должно быть решение, выбранное Apple, вместо того, чтобы иметь отдельные ceil
и ceilf
функции, потому что они не имеют смысла в Swift.
С Swift 3, в соответствии с вашими потребностями, вы можете выбрать один из 4 следующим образом чтобы собрать CGFloat
.
#1. Используя FloatingPoint
протокол rounded(_:)
метод
FloatingPoint
протокол дает типы, которые соответствуют его rounded(_:)
метод. rounded(_:)
есть следующее объявление:
func rounded(_ rule: FloatingPointRoundingRule) -> Self
возвращает это значение, округленное до интегрального значения с использованием указанного округления правило.
код игровой площадки ниже показывает, как использовать rounded(_:)
для того, чтобы округлить CGFloat
значение:
import CoreGraphics
let value1: CGFloat = -0.4
let value2: CGFloat = -0.5
let value3: CGFloat = -1
let value4: CGFloat = 0.4
let value5: CGFloat = 0.5
let value6: CGFloat = 1
let roundedValue1 = value1.rounded(.up)
let roundedValue2 = value2.rounded(.up)
let roundedValue3 = value3.rounded(.up)
let roundedValue4 = value4.rounded(.up)
let roundedValue5 = value5.rounded(.up)
let roundedValue6 = value6.rounded(.up)
print(roundedValue1) // prints -0.0
print(roundedValue2) // prints -0.0
print(roundedValue3) // prints -1.0
print(roundedValue4) // prints 1.0
print(roundedValue5) // prints 1.0
print(roundedValue6) // prints 1.0
#2. Используя ceil(_:)
функции
Дарвин предоставляет ceil(_:)
функция, которая имеет следующий вид:
public func ceil<T : FloatingPoint>(_ x: T) -> T
код игровой площадки ниже показывает, как использовать ceil(_:)
для того, чтобы округлить CGFloat
значение:
import CoreGraphics
let value1: CGFloat = -0.4
let value2: CGFloat = -0.5
let value3: CGFloat = -1
let value4: CGFloat = 0.4
let value5: CGFloat = 0.5
let value6: CGFloat = 1
let roundedValue1 = ceil(value1)
let roundedValue2 = ceil(value2)
let roundedValue3 = ceil(value3)
let roundedValue4 = ceil(value4)
let roundedValue5 = ceil(value5)
let roundedValue6 = ceil(value6)
print(roundedValue1) // prints -0.0
print(roundedValue2) // prints -0.0
print(roundedValue3) // prints -1.0
print(roundedValue4) // prints 1.0
print(roundedValue5) // prints 1.0
print(roundedValue6) // prints 1.0
#3. С помощью NSDecimalNumber
NSDecimalNumber
предлагает подробное, но мощное решение для округления чисел.
import Foundation
import CoreGraphics
let value1: CGFloat = -0.4
let value2: CGFloat = -0.5
let value3: CGFloat = -1
let value4: CGFloat = 0.4
let value5: CGFloat = 0.5
let value6: CGFloat = 1
let scale: Int16 = 0
let behavior = NSDecimalNumberHandler(roundingMode: NSDecimalNumber.RoundingMode.up, scale: scale, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)
let roundedValue1 = NSDecimalNumber(value: Double(value1)).rounding(accordingToBehavior: behavior)
let roundedValue2 = NSDecimalNumber(value: Double(value2)).rounding(accordingToBehavior: behavior)
let roundedValue3 = NSDecimalNumber(value: Double(value3)).rounding(accordingToBehavior: behavior)
let roundedValue4 = NSDecimalNumber(value: Double(value4)).rounding(accordingToBehavior: behavior)
let roundedValue5 = NSDecimalNumber(value: Double(value5)).rounding(accordingToBehavior: behavior)
let roundedValue6 = NSDecimalNumber(value: Double(value6)).rounding(accordingToBehavior: behavior)
print(roundedValue1) // prints 0
print(roundedValue2) // prints 0
print(roundedValue3) // prints -1
print(roundedValue4) // prints 1
print(roundedValue5) // prints 1
print(roundedValue6) // prints 1
#4. Используя NumberFormatter
если вы хотите округлить CGFloat
и форматировать его со стилем в той же операции, вы можете использовать NumberFormatter
.
import Foundation
import CoreGraphics
let value1: CGFloat = -0.4
let value2: CGFloat = -0.5
let value3: CGFloat = -1
let value4: CGFloat = 0.4
let value5: CGFloat = 0.5
let value6: CGFloat = 1
let formatter = NumberFormatter()
formatter.numberStyle = NumberFormatter.Style.decimal
formatter.roundingMode = NumberFormatter.RoundingMode.ceiling
formatter.maximumFractionDigits = 0
let roundedValue1 = formatter.string(for: value1)
let roundedValue2 = formatter.string(for: value2)
let roundedValue3 = formatter.string(for: value3)
let roundedValue4 = formatter.string(for: value4)
let roundedValue5 = formatter.string(for: value5)
let roundedValue6 = formatter.string(for: value6)
print(String(describing: roundedValue1)) // prints Optional("-0")
print(String(describing: roundedValue2)) // prints Optional("-0")
print(String(describing: roundedValue3)) // prints Optional("-1")
print(String(describing: roundedValue4)) // prints Optional("1")
print(String(describing: roundedValue5)) // prints Optional("1")
print(String(describing: roundedValue6)) // prints Optional("1")
построение ответа холекса. Я сделал
func accurateRound(value: Double) -> Int {
var d : Double = value - Double(Int(value))
if d < 0.5 {
return Int(value)
} else {
return Int(value) + 1
}
}
- edit extension edition -
Я также недавно превратил это в расширение для поплавков, думал, что поделюсь:)
extension Float {
func roundToInt() -> Int{
var value = Int(self)
var f = self - Float(value)
if f < 0.5{
return value
} else {
return value + 1
}
}
}
Это делает его так что вы можете просто быть как
var f : Float = 3.3
f.roundToInt()
С Стандартная Библиотека Swift вы можете обойти его на месте, а также:
var value: CGFloat = -5.7
value.round(.up) // -5.0