Bir Çifti hızlı bir şekilde en yakın Int'ye nasıl yuvarlanırım?


170

DoubleEn yakın tamsayı sonucu yuvarlayacak ve oradan yeniden hesaplamak gibi büyüme oranı ( ) hesap makinesi yapmaya çalışıyorum :

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
}

ama şimdiye kadar yapamadım.

EDIT Ben böyle yaptım:

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
}

Her zaman aşağı yuvarladığı umrumda olmasa da, hoşlanmam çünkü firstUsersbir değişken olmak ve program boyunca (bir sonraki hesaplamayı yapmak için) değişmek zorunda kaldım, bunun olmasını istemiyorum.

Yanıtlar:


253

Bir yoktur roundbulunan Foundationkütüphanede (o aslında var Darwinama Foundationithalat Darwinve çoğu zaman kullanmak isteyeceksiniz Foundationkullanmak yerine Darwindoğrudan) .

import Foundation

users = round(users)

Kodunuzu bir oyun alanında çalıştırın ve sonra arayın:

print(round(users))

Çıktılar:

15.0

round()ondalık basamak her zaman yukarı >= .5ve aşağı < .5yuvarlanır (standart yuvarlama). Sen kullanabilirsiniz floor()yuvarlama aşağı zorlamak ve ceil()yuvarlama zorlamak için.

Eğer tarafından çarpın o zaman, belirli bir yere yuvarlak gerekiyorsa pow(10.0, number of places), roundve sonra bölün pow(10, number of places):

2 ondalık basamağa yuvarlayın:

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

Çıktılar:

10.12

Not: Kayan nokta matematik çalışma şekli nedeniyle, roundedher zaman tam olarak doğru olmayabilir. Daha iyi bir yuvarlama yaklaşımı düşünmek en iyisidir. Bunu görüntüleme amacıyla yapıyorsanız, sayıyı yuvarlamak için matematik kullanmak yerine dize biçimlendirmesi kullanmak daha iyidir.


Hmm pow()ne yazık ki bir oyun alanında mevcut değil
MrBr

1
@MrBr, pow()Darwin kütüphanesinde tanımlanmıştır, bu yüzden import Darwinönce (ya import Foundationda import Cocoaya da import UIKithepsi Darwin'i dahili olarak içe aktarmanız gerekir) gerekir.
Mike S

54
Ayrıca lround()bir döndüren vardır Int.
Martin R

1
" round()ondalık basamak> = .5 olduğunda daima yukarı, <.5 (standart yuvarlama) olduğunda aşağı yuvarlar." Olmadığı zamanlar hariç. round(-16.5)-16 döndürür, -16 değil. Bu bir hata mı?
Daniel T.

1
@DanielT. - böcek değil. En yakın negatif sayıya yuvarlanıyor. Bu şekilde düşünün, +16,5 - +17 sıfırdan 0,5 daha uzağa gidiyor. Bu, -16.5 ila -17'nin de sıfırdan 0.5 daha uzakta olduğu anlamına gelir. Tavan tam tersi olur, +16,5 - +16 sıfıra 0,5 daha yakın ve -16,5 - -16 da sıfıra 0,5 daha yakın
ergenler

139

Bir çifti en yakın tamsayıya yuvarlamak için tuşunu kullanın round().

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

Orijinal değeri değiştirmek istemiyorsanız şunu kullanın rounded():

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

Beklendiği gibi ( veya olmayabilir ), benzeri bir sayı 3.5yukarı yuvarlanır ve benzeri bir sayı -3.5yuvarlanır. Bundan farklı bir yuvarlama davranışına ihtiyacınız varsa, yuvarlama kurallarından birini kullanabilirsiniz . Örneğin:

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

Bir gerçek gerekiyorsa, Intsadece birine yayınlayın (ancak sadece Double'un daha büyük olmayacağından eminseniz Int.max):

let myInt = Int(myDouble.rounded())

notlar

  • Bu cevap tamamen yeniden yazılmıştır. Eski cevap matematik fonksiyonları gibi C ile ele round, lround, floor, ve ceil. Ancak, şimdi Swift bu işlevi yerleşik olarak, artık bu işlevleri kullanmanızı tavsiye edemez. @Dfri'ye bunu gösterdiği için teşekkürler. @ Dfri'nin mükemmel cevabına buradan göz atın . Ben de yuvarlamakCGFloat için benzer bir şey yaptım .

Int (myDouble.rounded ()) <--- çift Int
Toad

@Toad, emin misin? Bunu belgelerde görmüyorum .
Suragch

Bu sorunla üretimdeki bir çöküşü çözdüm. Ama yanılmış olsaydım ve çökmeyecek olsa bile, yine de çiftler> maxint için beklenmedik sonuçlar verecekti
Toad

1
@ Kurbağa, doğru, iyi bir nokta, teşekkürler. Cevaba bir not ekledim.
Suragch

85

Swift 3 & 4 - Protokolde rounded(_:)planlandığı gibi yöntemden yararlanmaFloatingPoint

FloatingPointProtokol (ki örn Doubleve Floatuygundur) ozalitler rounded(_:)yöntemi

func rounded(_ rule: FloatingPointRoundingRule) -> Self

Burada FloatingPointRoundingRulefarklı yuvarlama kurallarının bir dizi numaralandırma bir enum olan:

case awayFromZero

Büyüklüğü kaynağınkinden büyük veya ona eşit olan en yakın değere yuvarlayın.

case down

Kaynağa eşit veya daha küçük olan, izin verilen en yakın değere yuvarlayın.

case toNearestOrAwayFromZero

İzin verilen en yakın değere yuvarlayın; iki değer eşit derecede yakınsa, daha büyük büyüklüğe sahip olan seçilir.

case toNearestOrEven

İzin verilen en yakın değere yuvarlayın; iki değer eşit derecede yakınsa, çift değer seçilir.

case towardZero

Büyüklüğü kaynağınkinden küçük veya ona eşit olan en yakın değere yuvarlayın.

case up

Kaynağa eşit veya daha büyük, izin verilen en yakın değere yuvarlayın.

Uygulamada bu farklı yuvarlama seçeneklerini göstermek için @ Suragch'ın mükemmel cevabından benzer örnekleri kullanıyoruz .

.awayFromZero

Büyüklüğü kaynağınkinden büyük veya ona eşit olan en yakın değere yuvarlayın; herhangi bir koşullu işaretine, bu kullanımlar için, C işlevleri arasında eşdeğer doğrudan self, ceilya da floorpozitif ve negatif değerleri için, selfsırasıyla.

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 floorişlevine eşdeğerdir .

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 roundişlevine eşdeğerdir .

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

Bu yuvarlama kuralına sıfır argüman rounded()yöntemi kullanılarak da erişilebilir .

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

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

.toNearestOrEven

İzin verilen en yakın değere yuvarlayın; iki değer eşit derecede yakınsa, çift değer seçilir; C rint(/ çok benzer nearbyint) fonksiyonuna eşdeğerdir .

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 truncişlevine eşdeğerdir .

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

Yuvarlama amacı (örn kullanarak bir tamsayı ile işe hazırlamak için ise Inttarafından FloatPointyuvarlama sonra başlatma), biz sadece bir başlatılıyor gerçeği faydalanmak olabilir Intbir kullanarak Double(veya Floatondalık kısım uzakta kesilir vs).

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 ceilişlevine eşdeğerdir .

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

Ek: FloatingPointC işlevlerinin farklı FloatingPointRoundingRulekurallara eşdeğer olduğunu doğrulamak için kaynak kodunu ziyaret etme

FloatingPointİstersek, doğrudan ortak FloatingPointRoundingRulekurallara C işlevi eşdeğerlerini görmek için protokolün kaynak koduna bakabiliriz .

Gönderen hızlı / stdlib / kamu / çekirdek / FloatingPoint.swift.gyb biz varsayılan uygulaması görüyoruz rounded(_:)yöntemin mutasyona bize yapar round(_:)yöntemiyle:

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

Gönderen Swift / stdlib / kamu / çekirdek / FloatingPointTypes.swift.gyb biz varsayılan uygulamasını bulmak round(_:)arasındaki denklik hangi, FloatingPointRoundingRulekural ve işlevleri yuvarlama C belirgindir:

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 bilgi istemi için teşekkürler, cevap başlığını güncelledim.
dfri

3.0 = 3, 3.1 = 3.5, 3.4 = 3.5, 3.6 = 4, 3.9 - 4
PJR,

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: Belirli bir basamak numarasına yuvarlamak istiyorsanız, örneğin 5.678434 -> 5.68, round () veya roundf () işlevini çarpma ile birleştirebilirsiniz:

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

4

Ayrıca Swift 3'te FloatingPoint'i aşağıdaki gibi genişletebilirsiniz:

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

    }
}

324.0.rounded(to: 5)   // 325

Bunu açıklayabilir misiniz? Ne Selfanlama geliyor?
JZAU

@Jacky Self, FloatingPoint sınıfını ifade ederken, benlik bu sınıf örneğini ifade eder.
George Yacoub

@GeorgeYacoub Self, genişletilen FloatingPoint'e uyan türü ifade eder (bu örnek kullanımda bir Double'dir), ancak sınıflar değil yapılardır
Leo Dabus

2

Hızlı 3

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

Güzel. Bunu daha önce bilmiyordum. Bir not: myNum.rounded()değişmez myNum, ancak değişir myNum.round().
Suresi

@Suragch, cevabınızı yorumunuzu yansıtacak şekilde düzenledim.
Adil Hussain

0

Değeri bir Int'ye dönüştürmeye çalışmadan önce, çiftin max Int değerinden daha yüksek olup olmadığını da kontrol etmek isteyebilirsiniz.

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

-1

Benim için çok kolay bir çözüm çalıştı:

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

sayı 2 değerini içeriyor

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.