如何在Swift中将小数截断为x位置

时间:2016-03-11 17:37:07

标签: ios swift double decimal calculator

在我的swift程序中,我有一个非常长的十进制数(比如17.9384693864596069567),我想将小数截断到几个小数位(所以我希望输出为17.9384)。我想要将数字四舍五入到17.9385。我怎么能这样做?

非常感谢帮助!

注意:这不是重复的,因为在使用其中一些函数之前,它们使用的是旧版本的swift。此外,他们使用浮点数和整数,而我说的是双打。他们的问题/答案要复杂得多。

10 个答案:

答案 0 :(得分:25)

通过将其作为Double

的扩展,您可以进一步整理此内容
extension Double
{
    func truncate(places : Int)-> Double
    {
        return Double(floor(pow(10.0, Double(places)) * self)/pow(10.0, Double(places)))
    }
}

你就像这样使用它

var num = 1.23456789
// return the number truncated to 2 places
print(num.truncate(places: 2))

// return the number truncated to 6 places
print(num.truncate(places: 6))

答案 1 :(得分:4)

小数点后的特定数字代码为:

let number = 17.9384693864596069567;
let merichle = Float(String(format: "%.1f", (number * 10000)).dropLast(2))!/10000

//merichle = 17.9384

最终,你的号码在没有回合的情况下被截断...

答案 2 :(得分:3)

我想出了这个。

只是在地板上(向下舍入)这个数字,带有一些花哨的技巧。

let x = 1.23556789
let y = Double(floor(10000*x)/10000) // leaves on first four decimal places
let z = Double(floor(1000*x)/1000) // leaves on first three decimal places
print(y) // 1.2355
print(z) // 1.235

因此,乘以1并将0的数量作为您想要的小数位数,将其除以乘以它的乘以。瞧。

答案 3 :(得分:3)

您可以通过以下方法使其变得简单:

String(format: "%.0f", ratio*100)

其中0是要允许的小数位数。在这种情况下为零。比率是两倍:0.5556633。 希望能帮助到你。

答案 4 :(得分:2)

快速将5截断为小数也可以通过创建扩展为小数

extension Decimal {
  func truncation(by digit: Int) -> Decimal {
    var initialDecimal = self
    var roundedDecimal = Decimal()
    NSDecimalRound(&roundedDecimal, &initialDecimal, digit, .plain)
    return roundedDecimal
  }

十进制值的用例

value = Decimal(2.56430).truncation(by:2)

值= 2.560000(截断后)

答案 5 :(得分:1)

SwiftUI: 如果要截断视图中的格式而不是计算格式,SwiftUI包含一种方便的方式来使用C格式说明符作为Text()签名的一部分。

import SwiftUI

let myDouble = 17.93846938645960695
Text("\(myDouble, specifier: "%.2f")")
///Device display: 17.94

上面的代码会将Double的内容直接输出到View,正确舍入到第100位,但保留Double的值以供进一步计算。

如果作为SwiftUI的用户您不熟悉C语言格式说明符,则此链接包含有用的信息:https://en.wikipedia.org/wiki/Printf_format_string

答案 6 :(得分:1)

方式 1:如果您不想为此创建任何新函数,您可以通过这种方式直接获取四舍五入的值。

var roundedValue = (decimalValue * pow(10.0, Double(numberOfPlaces))).rounded())/pow(10.0, Double(numberOfPlaces)

示例:

var numberOfPlaces = 2
var decimalValue = 13312.2423423523523

print("\(((decimalValue * pow(10.0, Double(numberOfPlaces))).rounded())/pow(10.0, Double(numberOfPlaces)))")

结果:1​​3312.24



方式 2:如果您只是想打印,可以使用:

print(String(format: "%.\(numberOfPlaces)f",decimalValue))

示例

var numberOfPlaces = 4
var decimalValue = 13312.2423423523523

print(String(format: "%.\(numberOfPlaces)f",decimalValue))

答案 7 :(得分:0)

拖放解决方案,IOS,Swift 4

将此代码复制到您的应用程序中...

import Foundation

func truncateDigitsAfterDecimal(number: Double, afterDecimalDigits: Int) -> Double {
   if afterDecimalDigits < 1 || afterDecimalDigits > 512 {return 0.0}
   return Double(String(format: "%.\(afterDecimalDigits)f", number))!
}

然后您可以像下面这样调用此函数:

truncateDigitsAfterDecimal(number: 45.123456789, afterDecimalDigits: 3)

将产生以下内容:

45.123

答案 8 :(得分:0)

extension Double {
    /// Rounds the double to decimal places value
    func roundToPlaces(_ places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
    func cutOffDecimalsAfter(_ places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self*divisor).rounded(.towardZero) / divisor
    }
}

let a:Double = 1.228923598

print(a.roundToPlaces(2)) // 1.23
print(a.cutOfDecimalsAfter(2)) // 1.22

答案 9 :(得分:0)

Swift 5.2的答案

我看了很多答案,截断时总是遇到转换问题。根据我的数学知识,通过截断可以理解,如果我有3.1239并且想要3个小数,那么我将有3.123,不进行舍入(!= 3.1234)。

也许,由于流程的本质,我在Doubles上总是很成功,但在Floats上总是遇到问题。

我的方法是创建BinaryFloatingPoint的扩展,以便可以将其重用于Float,CGFLoat,Double ...

以下扩展获取了BinaryFloatingPoint,并且可以返回具有给定numberOfDecimals的String或BinaryFloatingPoint值,并且可以处理不同类型的情况:

extension Numeric where Self: BinaryFloatingPoint {
    
    /// Retruns the string value of the BinaryFloatingPoint. The initiaiser
    var toString: String {
        return String(describing: self)
    }
    
    /// Returns the number of decimals. It will be always greater than 0
    var numberOfDecimals: Int {
        return toString.count - String(Int(self)).count - 1
    }
   
    /// Returns a Number with a certain number of decimals
    /// - Parameters:
    ///   - Parameter numberOfDecimals: Number of decimals to return
    /// - Returns: BinaryFloatingPoint with number of decimals especified
    func with(numberOfDecimals: Int) -> Self {
        let stringValue = string(numberOfDecimals: numberOfDecimals)
        if self is Double {
            return Double(stringValue) as! Self
        } else {
            return Float(stringValue) as! Self
        }
    }
    
    /// Returns a string representation with a number of decimals
    /// - Parameters:
    ///   - Parameter numberOfDecimals: Number of decimals to return
    /// - Returns: String with number of decimals especified
    func string(numberOfDecimals: Int) -> String {
        let selfString = toString
        let selfStringComponents = selfString.components(separatedBy: ".")
        let selfStringIntegerPart = selfStringComponents[0]
        let selfStringDecimalPart = selfStringComponents[1]
        
        if numberOfDecimals == 0 {
            return selfStringIntegerPart
        } else {
            if selfStringDecimalPart.count == numberOfDecimals {
                return [selfStringIntegerPart,
                        selfStringDecimalPart].joined(separator: ".")
            } else {
                if selfStringDecimalPart.count > numberOfDecimals {
                    return [selfStringIntegerPart,
                            String(selfStringDecimalPart.prefix(numberOfDecimals))].joined(separator: ".")
                } else {
                    let difference = numberOfDecimals - selfStringDecimalPart.count
                    let addedCharacters = [Character].init(repeating: "0", count: difference)
                    
                    return [selfStringIntegerPart,
                            selfStringDecimalPart+addedCharacters].joined(separator: ".")
                }
            }
        }
    }
        
}

看似老派,但我所有的考试都通过了:

func test_GivenADecimalNumber_ThenAssertNumberOfDecimalsWanted() {
   //No decimals
    XCTAssertEqual(Float(3).with(numberOfDecimals: 0), 3)
    XCTAssertEqual(Float(3.09).with(numberOfDecimals: 0), 3)
    XCTAssertEqual(Float(3.999).with(numberOfDecimals: 0), 3)
    
    XCTAssertEqual(Double(3).with(numberOfDecimals: 0), 3)
    XCTAssertEqual(Double(3.09).with(numberOfDecimals: 0), 3)
    XCTAssertEqual(Double(3.999).with(numberOfDecimals: 0), 3)
    
    
    //numberOfDecimals == totalNumberOfDecimals
    XCTAssertEqual(Float(3.00).with(numberOfDecimals: 2), 3.00)
    XCTAssertEqual(Float(3.09).with(numberOfDecimals: 2), 3.09)
    XCTAssertEqual(Float(3.01).with(numberOfDecimals: 2), 3.01)
    XCTAssertEqual(Float(3.999).with(numberOfDecimals: 3), 3.999)
    XCTAssertEqual(Float(3.991).with(numberOfDecimals: 3), 3.991)
    
    XCTAssertEqual(Double(3.00).with(numberOfDecimals: 2), 3.00)
    XCTAssertEqual(Double(3.09).with(numberOfDecimals: 2), 3.09)
    XCTAssertEqual(Double(3.01).with(numberOfDecimals: 2), 3.01)
    XCTAssertEqual(Double(3.999).with(numberOfDecimals: 3), 3.999)
    XCTAssertEqual(Double(3.991).with(numberOfDecimals: 3), 3.991)
    
    
    //numberOfDecimals < totalNumberOfDecimals
    XCTAssertEqual(Float(3.00).with(numberOfDecimals: 1), 3.0)
    XCTAssertEqual(Float(3.09).with(numberOfDecimals: 1), 3.0)
    XCTAssertEqual(Float(3.01).with(numberOfDecimals: 1), 3.0)
    XCTAssertEqual(Float(3.999).with(numberOfDecimals: 2), 3.99)
    XCTAssertEqual(Float(3.991).with(numberOfDecimals: 2), 3.99)
    
    XCTAssertEqual(Double(3.00).with(numberOfDecimals: 1), 3.0)
    XCTAssertEqual(Double(3.09).with(numberOfDecimals: 1), 3.0)
    XCTAssertEqual(Double(3.01).with(numberOfDecimals: 1), 3.0)
    XCTAssertEqual(Double(3.999).with(numberOfDecimals: 2), 3.99)
    XCTAssertEqual(Double(3.991).with(numberOfDecimals: 2), 3.99)
    
    
    //numberOfDecimals > totalNumberOfDecimals
    XCTAssertEqual(Float(3.00).with(numberOfDecimals: 3), 3.000)
    XCTAssertEqual(Float(3.09).with(numberOfDecimals: 3), 3.090)
    XCTAssertEqual(Float(3.01).with(numberOfDecimals: 3), 3.010)
    XCTAssertEqual(Float(3.999).with(numberOfDecimals: 4), 3.9990)
    XCTAssertEqual(Float(3.991).with(numberOfDecimals: 4), 3.9910)
    
    XCTAssertEqual(Double(3.00).with(numberOfDecimals: 3), 3.000)
    XCTAssertEqual(Double(3.09).with(numberOfDecimals: 3), 3.090)
    XCTAssertEqual(Double(3.01).with(numberOfDecimals: 3), 3.010)
    XCTAssertEqual(Double(3.999).with(numberOfDecimals: 4), 3.9990)
    XCTAssertEqual(Double(3.991).with(numberOfDecimals: 4), 3.9910)
}

func test_GivenADecimal_ThenAssertStringValueWithDecimalsWanted() {
    //No decimals
    XCTAssertEqual(Float(3).string(numberOfDecimals: 0), "3")
    XCTAssertEqual(Float(3.09).string(numberOfDecimals: 0), "3")
    XCTAssertEqual(Float(3.999).string(numberOfDecimals: 0), "3")
    
    XCTAssertEqual(Double(3).string(numberOfDecimals: 0), "3")
    XCTAssertEqual(Double(3.09).string(numberOfDecimals: 0), "3")
    XCTAssertEqual(Double(3.999).string(numberOfDecimals: 0), "3")
    
    
    //numberOfDecimals == totalNumberOfDecimals
    XCTAssertEqual(Float(3.00).string(numberOfDecimals: 2), "3.00")
    XCTAssertEqual(Float(3.09).string(numberOfDecimals: 2), "3.09")
    XCTAssertEqual(Float(3.01).string(numberOfDecimals: 2), "3.01")
    XCTAssertEqual(Float(3.999).string(numberOfDecimals: 3), "3.999")
    XCTAssertEqual(Float(3.991).string(numberOfDecimals: 3), "3.991")
    
    XCTAssertEqual(Double(3.00).string(numberOfDecimals: 2), "3.00")
    XCTAssertEqual(Double(3.09).string(numberOfDecimals: 2), "3.09")
    XCTAssertEqual(Double(3.01).string(numberOfDecimals: 2), "3.01")
    XCTAssertEqual(Double(3.999).string(numberOfDecimals: 3), "3.999")
    XCTAssertEqual(Double(3.991).string(numberOfDecimals: 3), "3.991")
    
    
    //numberOfDecimals < totalNumberOfDecimals
    XCTAssertEqual(Float(3.00).string(numberOfDecimals: 1), "3.0")
    XCTAssertEqual(Float(3.09).string(numberOfDecimals: 1), "3.0")
    XCTAssertEqual(Float(3.01).string(numberOfDecimals: 1), "3.0")
    XCTAssertEqual(Float(3.999).string(numberOfDecimals: 2), "3.99")
    XCTAssertEqual(Float(3.991).string(numberOfDecimals: 2), "3.99")
    
    XCTAssertEqual(Double(3.00).string(numberOfDecimals: 1), "3.0")
    XCTAssertEqual(Double(3.09).string(numberOfDecimals: 1), "3.0")
    XCTAssertEqual(Double(3.01).string(numberOfDecimals: 1), "3.0")
    XCTAssertEqual(Double(3.999).string(numberOfDecimals: 2), "3.99")
    XCTAssertEqual(Double(3.991).string(numberOfDecimals: 2), "3.99")
    
    
    //numberOfDecimals > totalNumberOfDecimals
    XCTAssertEqual(Float(3.00).string(numberOfDecimals: 3), "3.000")
    XCTAssertEqual(Float(3.09).string(numberOfDecimals: 3), "3.090")
    XCTAssertEqual(Float(3.01).string(numberOfDecimals: 3), "3.010")
    XCTAssertEqual(Float(3.999).string(numberOfDecimals: 4), "3.9990")
    XCTAssertEqual(Float(3.991).string(numberOfDecimals: 4), "3.9910")
    
    XCTAssertEqual(Double(3.00).string(numberOfDecimals: 3), "3.000")
    XCTAssertEqual(Double(3.09).string(numberOfDecimals: 3), "3.090")
    XCTAssertEqual(Double(3.01).string(numberOfDecimals: 3), "3.010")
    XCTAssertEqual(Double(3.999).string(numberOfDecimals: 4), "3.9990")
    XCTAssertEqual(Double(3.991).string(numberOfDecimals: 4), "3.9910")
}