Checking if a double value is an integer - Swift

后端 未结 12 2000
梦如初夏
梦如初夏 2020-12-14 14:18

I need to check if a double-defined variable is convertible to Int without losing its value. This doesn\'t work because they are of different types:

if self.         


        
相关标签:
12条回答
  • 2020-12-14 14:30

    Try 'flooring' the double value then checking if it is unchanged:

    let dbl = 2.0
    let isInteger = floor(dbl) == dbl // true
    

    Fails if it is not an integer

    let dbl = 2.4
    let isInteger = floor(dbl) == dbl // false
    
    0 讨论(0)
  • 2020-12-14 14:39

    BECAREFUL.

    truncatingRemainder(dividingBy:) can be tricky. See below:

    Swift 4:

    //case 1
    let reminder = (4.1 * 100).truncatingRemainder(dividingBy: 1.0)
    
    //case 2
    let reminder2 = (410).truncatingRemainder(dividingBy: 1.0)
    
    // reminder = 0.9999999999999432
    // reminder2 = 0 
    
    0 讨论(0)
  • 2020-12-14 14:41

    A small extension to check for this:

    extension FloatingPoint {
        var isInt: Bool {
            return floor(self) == self
        }
    }
    

    Then just do

    let anInt = 1.isInt
    let nonInt = 3.142.isInt
    
    0 讨论(0)
  • 2020-12-14 14:41

    How about converting the Double to an Int (which will cut off decimals), then back to a Double, then comparing this to the original Double? For example:

    var dbl:Double = 22/3
    dbl == Double(Int(dbl))
    // false: dbl = 7.33333... Double(Int(dbl)) = 7.0
    
    dbl = 25
    dbl == Double(Int(dbl))
    // true: dbl = 25.0, Double(Int(dbl)) = 25.0
    
    0 讨论(0)
  • 2020-12-14 14:43

    There is now an Int(exactly:) initializer that will tell you this directly without the problem of out-of-range whole numbers.

    if Int(exactly: self) != nil { ... }
    

    This will only return a non-nil value if the result can actually be stored in Int exactly. There are many Double values that are "integers" but will not fit in an Int. (See MartinR's comment on the accepted answer.)

    0 讨论(0)
  • 2020-12-14 14:48

    Using @ColinE answer, I build an extension that handles when the Double cannot be converted to Int and another function that returns the Int:

    extension Double {
    
        func isInt() -> Bool {
            guard Double(Int.min) <= self && self <= Double(Int.max) else {
                return false
            }
    
            return floor(self) == self
        }
    
        func toInt() -> Int? {
            guard Double(Int.min) <= self && self <= Double(Int.max) else {
                return nil
            }
    
            return Int(self)
        }
    }
    

    I hope this helps someone,

    Xavi

    0 讨论(0)
提交回复
热议问题