round - ceil swift 3
ReĂșna un CGFloat en Swift (5)
¿Cómo puedo reunir un CGFloat en Swift? He intentado ceil(CDouble(myCGFloat))
pero eso solo funciona en iPad Air y iPhone 5S.
Cuando se ejecuta en otro dispositivo simulado ''NSNumber'' is not a subtype of ''CGFloat''
un error que dice ''NSNumber'' is not a subtype of ''CGFloat''
Actualización : Apple ahora ha definido algunas versiones específicas de CGFloat de funciones comunes como ceil
:
func ceil(x: CGFloat) -> CGFloat
... específicamente para hacer frente a la diferencia de 32/64 bits. Si simplemente usa ceil
con un argumento CGFloat, ahora debería funcionar en todas las arquitecturas.
Mi respuesta original:
Esto es bastante horrible, creo, pero ¿alguien puede pensar en una mejor manera? #if
si no parece funcionar para CGFLOAT_IS_DOUBLE
; Creo que está limitado a crear configuraciones, por lo que puedo ver en la documentación para la compilación condicional .
var x = CGFloat(0.5)
#if arch(x86_64) || arch(arm64)
var test = ceil(x)
#else
var test = ceilf(x)
#endif
Construyendo fuera de la respuesta de holex. yo si
func accurateRound(value: Double) -> Int {
var d : Double = value - Double(Int(value))
if d < 0.5 {
return Int(value)
} else {
return Int(value) + 1
}
}
-edición de extensión deedit-
También recientemente convertí esto en una extensión para que Floats pensara que compartiría también :)
extension Float {
func roundToInt() -> Int{
var value = Int(self)
var f = self - Float(value)
if f < 0.5{
return value
} else {
return value + 1
}
}
}
Esto lo hace para que puedas ser como
var f : Float = 3.3
f.roundToInt()
eso puede ser útil:
func roundUp(value: Double) -> Int {
if value == Double(Int(value)) {
return Int(value)
} else if value < 0 {
return Int(value)
} else {
return Int(value) + 1
}
}
La sintaxis más correcta sería probablemente:
var f: CGFloat = 2.5
var roundedF = CGFloat(ceil(Double(f)))
Para usar CGFloat
primero voy a hacer que CGFloat
Double
y después del techo, lo vuelvo a convertir en CGFloat
.
Eso funciona cuando CGFloat
se define como CFloat
o CDouble
.
También podría definir un ceil
para flotantes ( Esto se ha implementado realmente en Swift 2 ):
func ceil(f: CFloat) -> CFloat {
return ceilf(f)
}
Entonces podrás llamar directamente
var roundedF: CGFloat = ceil(f)
mientras se preserva la seguridad del tipo.
De hecho, creo que esta debería ser la solución elegida por Apple, en lugar de tener funciones de ceilf
y ceilf
separadas porque no tienen sentido en Swift.
Con Swift 3, de acuerdo con sus necesidades, puede elegir una de las 4 formas siguientes de redondear un CGFloat
.
# 1. Utilizando el método rounded(_:)
protocolo FloatingPoint
FloatingPoint
protocolo FloatingPoint
proporciona tipos que conforman un método rounded(_:)
. rounded(_:)
tiene la siguiente declaración:
func rounded(_ rule: FloatingPointRoundingRule) -> Self
Devuelve este valor redondeado a un valor integral usando la regla de redondeo especificada.
El código de Playground a continuación muestra cómo usar rounded(_:)
para redondear un valor de 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. Usando la función ceil(_:)
Darwin proporciona una función ceil(_:)
que tiene la siguiente declaración:
public func ceil<T : FloatingPoint>(_ x: T) -> T
El código de Playground a continuación muestra cómo usar ceil(_:)
para redondear un valor de 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. Usando NSDecimalNumber
NSDecimalNumber
ofrece una solución detallada pero potente para redondear números.
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. Usando el método de protocolo NumberFormatter
Si desea redondear un CGFloat
y formatearlo con estilo en la misma operación, puede usar 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")