web-dev-qa-db-ja.com

SwiftでCGFloatを切り上げます

SwiftでCGFloatを切り上げるにはどうすればよいですか? ceil(CDouble(myCGFloat))を試しましたが、iPad AirとiPhone 5Sでのみ機能します。

別のシミュレートされたデバイスで実行すると、'NSNumber' is not a subtype of 'CGFloat'というエラーが表示されます

71
Oskar Persson

Update:Appleは、ceilのような一般的な関数のCGFloat固有のバージョンをいくつか定義しました。

func ceil(x: CGFloat) -> CGFloat

...特に32/64ビットの違いに対処するため。 ceilをCGFloat引数とともに使用するだけで、すべてのアーキテクチャで動作するようになります。

私の元の答え:

これはかなり恐ろしいことだと思いますが、だれかがもっと良い方法を考えられますか? #ifCGFLOAT_IS_DOUBLEで機能しないようです。 条件付きコンパイルのドキュメントで確認できます から、ビルド構成に制限されていると思います。

var x = CGFloat(0.5)

#if Arch(x86_64) || Arch(arm64)
var test = ceil(x)
#else
var test = ceilf(x)
#endif
109
Matt Gibson

Swift 5では、CGFloatを切り上げるために、3つのパスのいずれかを選択できます。


#1。 CGFloatrounded(_:)メソッドを使用する

FloatingPointプロトコルは、それに準拠する型に rounded(_:) メソッドを与えます。 CGFloatrounded(_:)には次の宣言があります。

func rounded(_ rule: FloatingPointRoundingRule) -> CGFloat

指定された丸め規則を使用して整数値に丸められたこの値を返します。

以下のPlaygroundサンプルコードは、CGFloat値を切り上げるためにrounded(_:)を使用する方法を示しています。

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(_:)関数を使用する

Darwinは、次の宣言を持つceil(_:)関数を提供します。

func ceil<T>(_ x: T) -> T where T : FloatingPoint

以下のPlaygroundコードは、CGFloat値を切り上げるためにceil(_:)を使用する方法を示しています。

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。 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")
28
Imanou Petit

最も正しい構文はおそらく次のとおりです。

var f: CGFloat = 2.5
var roundedF = CGFloat(ceil(Double(f)))

ceilを使用するには、最初にCGFloatDoubleにし、シーリング後にCGFloatに変換します。

CGFloatCFloatまたはCDoubleとして定義されている場合に機能します。

フロートに対してceilを定義することもできます(これは実際にSwift 2で実装されています):

func ceil(f: CFloat) -> CFloat {
   return ceilf(f)
}

その後、直接電話をかけることができます

var roundedF: CGFloat = ceil(f)

型の安全性を保ちながら。

私は実際、これは、Swiftで意味をなさないため、別個のceilおよびceilf関数を持つのではなく、Appleが選択したソリューションであると信じています。

20
Sulthan

from Swift Standard Library 同様にインプレースで丸めることができます:

var value: CGFloat = -5.7
value.round(.up) // -5.0
7
holex

Holexの答えから構築します。やった

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()
5
Krtko

Swift 5で使用します

let x = 6.5

// Equivalent to the C 'round' function:
print(x.rounded(.toNearestOrAwayFromZero))
// Prints "7.0"

// Equivalent to the C 'trunc' function:
print(x.rounded(.towardZero))
// Prints "6.0"

// Equivalent to the C 'ceil' function:
print(x.rounded(.up))
// Prints "7.0"

// Equivalent to the C 'floor' function:
print(x.rounded(.down))
// Prints "6.0"
0
mohsen