Doubleを最も近いIntにすばやく丸める方法は?


170

Double結果を最も近い整数に丸め、そこから再計算する成長率の計算機()を作成しようとしています。

let firstUsers = 10.0
let growth = 0.1
var users = firstUsers
var week = 0


while users < 14 {
    println("week \(week) has \(users) users")
    users += users * growth
    week += 1
}

しかし、私は今のところできませんでした。

編集 私はちょっとそのようにしました:

var firstUsers = 10.0
let growth = 0.1
var users:Int = Int(firstUsers)
var week = 0


while users <= 14 {
    println("week \(week) has \(users) users")
    firstUsers += firstUsers * growth
    users = Int(firstUsers)
    week += 1
}

常に切り捨てられていてもかまいませんfirstUsersが、変数になり、プログラム全体で変更する必要があり(次の計算を行うため)、それが発生しないようにする必要があるため、気になりません。

回答:


253

ライブラリにはがround用意されていFoundationます(実際にはDarwinにありますが、ほとんどの場合、直接使用する代わりにFoundationインポートDarwinを使用FoundationDarwinます)

import Foundation

users = round(users)

プレイグラウンドでコードを実行してから、次を呼び出します。

print(round(users))

出力:

15.0

round()常に小数点以下の場所があるときに切り上げ>= .5、それはだダウン< .5(標準の丸め)。を使用floor()して、切り捨てを強制したり、ceil()切り上げを強制したりできます。

特定の場所に丸める必要がある場合は、、、を乗算しpow(10.0, number of places)round次にで除算しpow(10, number of places)ます。

小数点以下2桁に丸める:

let numberOfPlaces = 2.0
let multiplier = pow(10.0, numberOfPlaces)
let num = 10.12345
let rounded = round(num * multiplier) / multiplier
print(rounded)

出力:

10.12

注:浮動小数点演算の方法により、rounded必ずしも完全に正確であるとは限りません。丸めの近似値と考えるとよいでしょう。表示目的でこれを行う場合は、数値を四捨五入するために数学を使用するよりも、文字列フォーマットを使用して数値をフォーマットする方が良いです。


うーんpow()遊び場で、残念ながら利用できません
MrBr

1
@MrBr pow()はDarwinライブラリで定義されているため、import Darwin最初に(またはimport Foundationor import Cocoaまたはimport UIKit、すべてが内部的にDarwinをインポートすることになる)必要があります。
Mike S

54
lround()を返すものもありますInt
マーティンR

1
round()小数点以下が0.5以上の場合は常に切り上げ、0.5未満の場合は切り捨てます(標準の丸め)。」そうでない場合を除いて。round(-16.5)-16ではなく-17を返します。これはバグですか?
ダニエルT.

1
@DanielT。-バグではありません。最も近い負の数に切り上げられます。このように考えてください。+ 16.5から+17は、ゼロから0.5だけ離れています。つまり、-16.5から-17も、ゼロから0.5だけ離れています。Ceilはその逆です。+ 16.5〜+16はゼロに0.5近く、
-16.5〜

139

doubleを最も近い整数に丸めるには、次のようにします。 round()

var x = 3.7
x.round() // x = 4.0

元の値を変更したくない場合は、 rounded()

let x = 3.7
let y = x.rounded() // y = 4.0. x = 3.7

予想されるように(またはそうでない場合もあります)、のような数値3.5は切り上げられ、のような数値-3.5は切り捨てられます。それとは異なる丸め動作が必要な場合は、いずれかの丸め規則を使用できます。例えば:

var x = 3.7
x.round(.towardZero) // 3.0

実際が必要な場合は、Int1にキャストするだけです(ただし、Doubleがを超えないことが確実な場合のみInt.max)。

let myInt = Int(myDouble.rounded())

ノート

  • この回答は完全に書き直されています。私の昔の答えは次のようにC数学関数を扱ってroundlroundfloor、とceil。ただし、Swiftにこの機能が組み込まれているため、これらの機能の使用はお勧めできません。これを私に指摘してくれた@dfriに感謝します。@dfriの優れた答えをここで確認してください。私もを丸めるCGFloatために同様のことをしまし

Int(myDouble.rounded())<--- doubleがIntに適合しない場合、実際には例外がスローされる可能性があります
Toad

@ヒキガエル、よろしいですか?私はそれをドキュメントに見ていません。
Suragch 2018年

私はちょうどこの正確な問題で生産のクラッシュを解決しました。しかし、私が間違っていてクラッシュしなかったとしても、それでもdoubles> maxintに対して予期しない結果が生じるでしょう
Toad

1
@ヒキガエル、正しい、良い点、ありがとう。回答にメモを追加しました。
Suragch 2018年

85

Swift 3&4- プロトコルにrounded(_:)ブループリントされている方法を利用FloatingPointする

FloatingPointプロトコル(例えばへDoubleFloat適合)は青写真rounded(_:)方法

func rounded(_ rule: FloatingPointRoundingRule) -> Self

FloatingPointRoundingRuleいくつかの異なる丸め規則を列挙する列挙型はどこにありますか:

case awayFromZero

その大きさがソースの大きさ以上である最も近い許容値に丸めます。

case down

ソース以下の最も近い許容値に丸めます。

case toNearestOrAwayFromZero

最も近い許容値に丸めます。2つの値が等しく近い場合は、大きさが大きい方の値が選択されます。

case toNearestOrEven

最も近い許容値に丸めます。2つの値が等しく近い場合は、偶数の値が選択されます。

case towardZero

絶対値がソースの絶対値以下の最も近い許容値に丸めます。

case up

ソース以上の最も近い許容値に丸めます。

@Suragchの優れた回答の例と同様の例を使用して、これらの異なる丸めオプションを実際に示します。

.awayFromZero

絶対値がソースの値以上の最も近い許容値に丸めます。Cの関数間で直接対応するものはありません。これは、それぞれの正の値と負の値に対して、条件に応じてselfceilまたはの符号を使用しているfloorためselfです。

3.000.rounded(.awayFromZero) // 3.0
3.001.rounded(.awayFromZero) // 4.0
3.999.rounded(.awayFromZero) // 4.0

(-3.000).rounded(.awayFromZero) // -3.0
(-3.001).rounded(.awayFromZero) // -4.0
(-3.999).rounded(.awayFromZero) // -4.0

.down

C floor関数と同等です。

3.000.rounded(.down) // 3.0
3.001.rounded(.down) // 3.0
3.999.rounded(.down) // 3.0

(-3.000).rounded(.down) // -3.0
(-3.001).rounded(.down) // -4.0
(-3.999).rounded(.down) // -4.0

.toNearestOrAwayFromZero

C round関数と同等です。

3.000.rounded(.toNearestOrAwayFromZero) // 3.0
3.001.rounded(.toNearestOrAwayFromZero) // 3.0
3.499.rounded(.toNearestOrAwayFromZero) // 3.0
3.500.rounded(.toNearestOrAwayFromZero) // 4.0
3.999.rounded(.toNearestOrAwayFromZero) // 4.0

(-3.000).rounded(.toNearestOrAwayFromZero) // -3.0
(-3.001).rounded(.toNearestOrAwayFromZero) // -3.0
(-3.499).rounded(.toNearestOrAwayFromZero) // -3.0
(-3.500).rounded(.toNearestOrAwayFromZero) // -4.0
(-3.999).rounded(.toNearestOrAwayFromZero) // -4.0

この丸め規則には、ゼロ引数rounded()メソッドを使用してアクセスすることもできます。

3.000.rounded() // 3.0
// ...

(-3.000).rounded() // -3.0
// ...

.toNearestOrEven

最も近い許容値に丸めます。2つの値が等しく近い場合は、偶数の値が選択されます。C rint(/と非常に類似nearbyint)関数と同等です。

3.499.rounded(.toNearestOrEven) // 3.0
3.500.rounded(.toNearestOrEven) // 4.0 (up to even)
3.501.rounded(.toNearestOrEven) // 4.0

4.499.rounded(.toNearestOrEven) // 4.0
4.500.rounded(.toNearestOrEven) // 4.0 (down to even)
4.501.rounded(.toNearestOrEven) // 5.0 (up to nearest)

.towardZero

C trunc関数と同等です。

3.000.rounded(.towardZero) // 3.0
3.001.rounded(.towardZero) // 3.0
3.999.rounded(.towardZero) // 3.0

(-3.000).rounded(.towardZero) // 3.0
(-3.001).rounded(.towardZero) // 3.0
(-3.999).rounded(.towardZero) // 3.0

丸めの目的は、(例えば、使用して整数値で動作するように準備している場合IntFloatPoint丸めた後の初期化)、我々は単に初期化するという事実を利用するかもしれないInt使用してDouble(またはFloat、小数部分が離れて切り捨てられますなど)。

Int(3.000) // 3
Int(3.001) // 3
Int(3.999) // 3

Int(-3.000) // -3
Int(-3.001) // -3
Int(-3.999) // -3

.up

C ceil関数と同等です。

3.000.rounded(.up) // 3.0
3.001.rounded(.up) // 4.0
3.999.rounded(.up) // 4.0

(-3.000).rounded(.up) // 3.0
(-3.001).rounded(.up) // 3.0
(-3.999).rounded(.up) // 3.0

補遺:のソースコードにアクセスしFloatingPointて、さまざまなFloatingPointRoundingRuleルールと同等のC関数を検証する

必要にFloatingPoint応じて、プロトコルのソースコードを見て、パブリックFloatingPointRoundingRuleルールに相当するC関数を直接確認できます。

より迅速/ STDLIB /公共/コア/ FloatingPoint.swift.gyb我々は、デフォルトの実装ことを確認rounded(_:)する方法は、変異の私たちを作るround(_:)方法:

public func rounded(_ rule: FloatingPointRoundingRule) -> Self {
    var lhs = self
    lhs.round(rule)
    return lhs
}

SWIFT / STDLIB /公共/コア/ FloatingPointTypes.swift.gyb我々はデフォルトの実装を見つけround(_:)、その中での等価性FloatingPointRoundingRuleルールとC丸め関数は明らかです。

public mutating func round(_ rule: FloatingPointRoundingRule) {
    switch rule {
    case .toNearestOrAwayFromZero:
        _value = Builtin.int_round_FPIEEE${bits}(_value)
    case .toNearestOrEven:
        _value = Builtin.int_rint_FPIEEE${bits}(_value)
    case .towardZero:
        _value = Builtin.int_trunc_FPIEEE${bits}(_value)
    case .awayFromZero:
        if sign == .minus {
            _value = Builtin.int_floor_FPIEEE${bits}(_value)
        }
        else {
            _value = Builtin.int_ceil_FPIEEE${bits}(_value)
        }
    case .up:
        _value = Builtin.int_ceil_FPIEEE${bits}(_value)
    case .down:
        _value = Builtin.int_floor_FPIEEE${bits}(_value)
    }
}

@iosMentalistプロンプトに感謝します。回答のタイトルを更新しました。
dfri

3.0 =
3、3.1

6
**In Swift**

var a = 14.123456789
var b = 14.123456789
var c = 14.123456789
var d = 14.123456789
var e = 14.123456789
var f = 14.123456789

a.rounded(.up)                      //15
b.rounded(.down)                    //14
c.rounded(.awayFromZero)            //15
d.rounded(.towardZero)              //14
e.rounded(.toNearestOrAwayFromZero) //14
f.rounded(.toNearestOrEven)         //14

6

Swift 3:特定の数字に丸めたい場合(例:5.678434-> 5.68)、round()関数またはroundf()関数を乗算と組み合わせるだけです。

let value:Float = 5.678434
let roundedValue = roundf(value * 100) / 100
print(roundedValue) //5.68

4

次のように、Swift 3でFloatingPointを拡張することもできます。

extension FloatingPoint {
    func rounded(to n: Int) -> Self {
        let n = Self(n)
        return (self / n).rounded() * n

    }
}

324.0.rounded(to: 5)   // 325

これについて説明していただけますか?どういうSelf意味?
JZAU 2017年

@Jacky SelfはクラスFloatingPointを参照しますが、selfはそのクラスのインスタンスを参照します。
ジョージヤコブ2017

@GeorgeYacoub Selfは、拡張されているFloatingPointに準拠するタイプを参照しますが(サンプルの使用法はDoubleです)、これらはクラスではなく構造です
Leo Dabus

2

スウィフト3

var myNum = 8.09
myNum.rounded() // result = 8 and leaves myNum unmodified

いいね。これについては以前は知りませんでした。注:myNum.rounded()変更されませんがmyNum、変更されmyNum.round()ます。
Suragch 16

@スラッグ、私はあなたのコメントを反映するために答えを編集しました。
アディルフセイン

0

値をIntに変換する前に、doubleが最大Int値より大きいかどうかを確認することもできます。

let number = Double.infinity
if number >= Double(integerLiteral: Int64.max) {
  let rounded = Int.max
} else {
  let rounded = Int(number.rounded())
}

-1

非常に簡単な解決策が私にとってうまくいきました:

  if (62 % 50 != 0) {
      var number = 62 / 50 + 1 // adding 1 is doing the actual "round up"
  }

数値に値2が含まれています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.