Swift - 如何在小数为0时从浮点数中去除小数?

120

我正在显示一个带有一位小数的距离,如果小数部分等于0,我想要将其删除(例如:1200.0公里),在Swift中该怎么做?我是这样显示这个数字的:

let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: "%.1f", distanceFloat) + "Km"

1
可能是 Swift - Remove Trailing Zeros From Double 的重复问题。 - Cœur
15个回答

186

Swift 3/4:

var distanceFloat1: Float = 5.0
var distanceFloat2: Float = 5.540
var distanceFloat3: Float = 5.03

extension Float {
    var clean: String {
       return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
    }
}

print("Value \(distanceFloat1.clean)") // 5
print("Value \(distanceFloat2.clean)") // 5.54
print("Value \(distanceFloat3.clean)") // 5.03

Swift 2 (Translated)

let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: distanceFloat == floor(distanceFloat) ? “%.0f" : "%.1f", distanceFloat) + "Km"

作为一种扩展方式:
extension Float {
    var clean: String {
        return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
    }
}

我在 distanceFloat = floor(distanceFloat * 10) / 10 前面添加了这行代码,然后它完美地工作了,谢谢 :) - Kalianey
2
对于 Double,扩展 Double { var clean: String { return self % 1 == 0 ? String(format: "%.0f", self) : String(self) } } - Atef
3
如果浮点数为3.01这样的数字,这种方法就不起作用。 - chengsam
需要将String(self)替换为"\(self)"。但是MirekE的答案更好。 - Nike Kov
@Abo3atef,%.0d%.0f有什么区别?我在我的Double扩展中使用后者,似乎运行良好。 - TimD
显示剩余2条评论

158

使用NSNumberFormatter:

let formatter = NumberFormatter()
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 2

// Avoid not getting a zero on numbers lower than 1
// Eg: .5, .67, etc...
formatter.numberStyle = .decimal

let nums = [3.0, 5.1, 7.21, 9.311, 600.0, 0.5677, 0.6988]

for num in nums {
    print(formatter.string(from: num as NSNumber) ?? "n/a")
}

返回:

3

5.1

7.21

9.31

600

0.57

0.7


7
Swift 3 的翻译:formatter.minimumFractionDigits = 0 formatter.maximumFractionDigits = 1 statLabel.text = formatter.string(from: value as NSNumber) ?? "n/a"``` 翻译为: ```使用 Swift 3: let formatter = NumberFormatter() formatter.minimumFractionDigits = 0 // 设置小数位最少为 0 formatter.maximumFractionDigits = 1 // 设置小数位最多为 1 statLabel.text = formatter.string(from: value as NSNumber) ?? "n/a" // 将格式化后的数字转换为字符串并赋值给 statLabel,如果转换失败则显示 "n/a"``` - alexxjk
1
0.3000怎么样?我试着用.get .3;来获取它; 我设置了它的样式formatter.numberStyle = .decimal - stan liu
@stanliu 是正确的,如果您不添加 .decimal numberStyle,小于1的数字将会显示为没有零的形式。例如:.5、.78等等... 现在正在编辑答案。 - HotFudgeSunday
我有一个数字 - 5.7156,但当我使用这个答案中的代码时,输出结果是5.72。有人知道为什么吗? - Ganesh Pawar
@GaneshPawar maximumFractionDigits 被设置为 2。如果您需要 4 个小数位,请将其设置为 4。 - Ankit Kumar Gupta

57

extension是一种强大的实现方式。

扩展(Extension)

Swift 2 的代码(不适用于 Swift 3 或更新版本):

extension Float {
    var cleanValue: String {
        return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
    }
}

使用方法:

var sampleValue: Float = 3.234
print(sampleValue.cleanValue)

3.234

sampleValue = 3.0
print(sampleValue.cleanValue)

3

sampleValue = 3
print(sampleValue.cleanValue)

3


示例Playground文件在这里


41

更新针对Swift 3的被接受答案:

extension Float {
    var cleanValue: String {
        return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
    }
}

使用方法只需要:

let someValue: Float = 3.0

print(someValue.cleanValue) //prints 3

23

要将它格式化为字符串,请按照以下模式进行

let aFloat: Float = 1.123

let aString: String = String(format: "%.0f", aFloat) // "1"
let aString: String = String(format: "%.1f", aFloat) // "1.1"
let aString: String = String(format: "%.2f", aFloat) // "1.12"
let aString: String = String(format: "%.3f", aFloat) // "1.123"

将其转换为整数,按照以下模式进行操作

let aInt: Int = Int(aFloat) // "1"

当您使用String(format:初始化程序时,Swift将根据以下数字自动四舍五入最终数字。


14

Swift 5.5让它变得更加容易

只需使用新的formatted() API,并使用默认的FloatingPointFormatStyle

let values: [Double] = [1.0, 4.5, 100.0, 7]
for value in values {
    print(value.formatted(FloatingPointFormatStyle()))
}
// prints "1, 4.5, 100, 7"

1
这应该是被接受的答案。 - Mani

11

你可以像之前提到的那样使用扩展程序,不过这个解决方案更加简洁:

extension Float {
    var shortValue: String {
        return String(format: "%g", self)
    }
}

示例用法:

var sample: Float = 3.234
print(sample.shortValue)

1
将会在 0.00000001 处失败。请参阅 http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html 上的 %g 文档:“所使用的样式取决于转换后的值;仅当此类转换产生的指数小于 -4 或大于等于精度时,才应使用样式 e(或 E)。” - Cœur

10

Swift 5对于双精度浮点数,与@Frankie关于单精度浮点数的答案相同。

var dec: Double = 1.0
dec.clean // 1

为了扩展

extension Double {
    var clean: String {
       return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
    }

}

8
在Swift 4中,请尝试以下操作。
    extension CGFloat{
        var cleanValue: String{
            //return String(format: 1 == floor(self) ? "%.0f" : "%.2f", self)
            return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.2f", self)//
        }
    }

//如何使用 - 如果您在小数点之后输入两个以上的字符,它会自动剪裁最后一个字符,并仅显示小数点后两个字符。

let strValue = "32.12"
print(\(CGFloat(strValue).cleanValue)

不会从值 1.1 中删除零:输出将为 "1.10" - Cœur
@Cœur 用于显示小数点后两个值。如果您只想显示一个值,则使用“return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.1f", self)//”。 - Berlin
我知道...我只是在描述你的代码与其他答案的行为有所不同。 - Cœur

5

格式化最大小数位,不保留末尾0

这种情况适用于需要自定义输出精度的情况。 此解决方案看起来与 NumberFormatter + NSNumber MirekE 的解决方案 差不多快,但一个好处是我们避免了 NSObject。

extension Double {
    func string(maximumFractionDigits: Int = 2) -> String {
        let s = String(format: "%.\(maximumFractionDigits)f", self)
        var offset = -maximumFractionDigits - 1
        for i in stride(from: 0, to: -maximumFractionDigits, by: -1) {
            if s[s.index(s.endIndex, offsetBy: i - 1)] != "0" {
                offset = i
                break
            }
        }
        return String(s[..<s.index(s.endIndex, offsetBy: offset)])
    }
}

(也适用于扩展浮点,但不适用于仅限于macOS的类型Float80

用法:myNumericValue.string(maximumFractionDigits: 2)myNumericValue.string()

maximumFractionDigits: 2的输出结果:

1.0 → "1"
0.12 → "0.12"
0.012 → "0.01"
0.0012 → "0"
0.00012 → "0"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接