Swift - Как удалить десятичную дробь из числа с плавающей запятой, если десятичная дробь равна 0?

88

Я показываю расстояние с одним десятичным знаком, и я хотел бы удалить это десятичное число, если оно равно 0 (например, 1200,0 км), как я могу сделать это быстро? Я показываю это число так:

let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: "%.1f", distanceFloat) + "Km"
Кали Эней
источник
1
Возможный дубликат Swift - Удалите конечные нули из двойных
Cœur

Ответы:

137

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 (оригинальный ответ)

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и она отлично сработала, спасибо :)
Kali Aney
1
Для Double расширение Double {var clean: String {return self% 1 == 0? Строка (формат: "% .0d", self): String (self)}}
Abo3atef
3
Это не сработает, если значение с плавающей запятой равно 3.01.
chengsam
А как насчет отрицательных чисел?
Happiehappie
Это не работает для этого числа 123456738.0, преобразованное число выглядит как 123456736
Махале
116

Используйте 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

MirekE
источник
2
идеальный ! Это должно быть на высоте
GoodSp33d
6
для Swift 3: let formatter = NumberFormatter() formatter.minimumFractionDigits = 0 formatter.maximumFractionDigits = 1 statLabel.text = formatter.string(from: value as NSNumber) ?? "n/a"
alexxjk
1
Как насчет 0,3000, пробую получить .3; Я установил свой стильformatter.numberStyle = .decimal
stan liu
@stanliu верен, если вы не добавите .decimalnumberStyle, номера ниже 1 будут отображаться без нуля. Например: 0,5, 0,78 и т. Д. Сейчас редактируем ответ.
HotFudge, воскресенье,
Я считаю, что это то, что Apple намерена решить такую ​​проблему.
DragonCherry
55

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 находится здесь .

Ашок
источник
1
Но 3.230000 -> 3.230000 ... как насчет "-> 3.23"?
CHiP-love-NY
1
@ CHiP-love-NY, я тебя не понял.
Ашок,
1
Я полагаю, он думает, что ваше расширение не удаляет конечные нули, но это так. String (3.230000) = "3.23"
jeffjv
34

Обновление принятого ответа для быстрого 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
Кристофер Ларсен
источник
Не работает когда ставишь т.е. 14.000005, конвертируется в 14.0
Vetuka
@ sc13 Ха, это странно, это произойдет, если вы увеличите его до 14.00000005, и в этот момент само число с плавающей точкой возвращает 14 без cleanValue. Думаю, это как-то связано с тем, как swift обрабатывает Float. Посмотрим, смогу ли я исправить эту ошибку.
Кристофер Ларсен
2
Я получаю правильный результат для 14.000005, поэтому комментарий @ sc13 кажется устаревшим или неправильным.
Cœur
10

Чтобы отформатировать его в String, следуйте этому шаблону

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"

Чтобы преобразовать его в Int, следуйте этому шаблону

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

Когда вы используете String(format:инициализатор, Swift автоматически округляет последнюю цифру по мере необходимости на основе следующего числа.

Baig
источник
Это не сработает, если значение равно 1.678
Саурав Нагпал,
@SauravNagpal Это сработает :)
Baig
9

Вы можете использовать расширение, как уже упоминалось, но это решение немного короче:

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

Пример использования:

var sample: Float = 3.234
print(sample.shortValue)
Линус
источник
1
Не получится 0.00000001. См. Документацию% g по адресу pubs.opengroup.org/onlinepubs/009695399/functions/printf.html : « Используемый стиль зависит от преобразованного значения; стиль e (или E) должен использоваться только в том случае, если показатель степени, полученный в результате такого преобразования меньше -4 или больше или равно точности »
Cœur
идеальный. Спасибо
PhillipJacobs
7

В 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) / / "
Джайдип
Я знаю ... Я просто описывал, чем ваш код отличается от поведения некоторых других ответов.
Cœur
4

NSNumberFormatter - ваш друг

let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
let numberFormatter = NSNumberFormatter()
numberFormatter.positiveFormat = "###0.##"
let distance = numberFormatter.stringFromNumber(NSNumber(float: distanceFloat))!
distanceLabel.text = distance + " Km"
вадиан
источник
4

Форматирование с максимальным количеством цифр дробной части, без конечных нулей

Этот сценарий хорош, когда требуется настраиваемая точность вывода. Это решение кажется примерно таким же быстрым, как решение 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)])
    }
}

(работает также extension Float, но не только с 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»

Cœur
источник
4

Swift 5 для Double, это то же самое, что и ответ @Frankie для float

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)
    }

}
Мохамед Шабан
источник
3

Вот полный код.

let numberA: Float = 123.456
let numberB: Float = 789.000

func displayNumber(number: Float) {
    if number - Float(Int(number)) == 0 {
        println("\(Int(number))")
    } else {
        println("\(number)")
    }
}

displayNumber(numberA) // console output: 123.456
displayNumber(numberB) // console output: 789

Вот самая важная строка в деталях.

func displayNumber(number: Float) {
  1. Удаляет десятичные цифры числа с плавающей запятой с помощью Int(number).
  2. Возвращает вырезанное число обратно в число с плавающей запятой для выполнения операции Float(Int(number)).
  3. Получает десятичное значение с number - Float(Int(number))
  4. Проверяет, что десятичное значение пусто, с помощью if number - Float(Int(number)) == 0

Содержимое операторов if и else не требует объяснения.

Прекрасный человек
источник
В вашем случае вы хотите, чтобы функция return Stringи вместо println(result)do return result. Надеюсь, это поможет!
Fine Man
3

Просто :

Int(floor(myFloatValue))
Ergunkocak
источник
Разве при этом не всегда удаляется десятичная дробь? OP этого не хочет.
Ракеша Шастри
2

Это тоже может быть полезно.

extension Float {
    func cleanValue() -> String {
        let intValue = Int(self)
        if self == 0 {return "0"}
        if self / Float (intValue) == 1 { return "\(intValue)" }
        return "\(self)"
    }
}

Применение:

let number:Float = 45.23230000
number.cleanValue()
Сантош Махарджан
источник
-1

Может быть, stringByReplacingOccurrencesOfStringмог бы вам помочь :)

let aFloat: Float = 1.000

let aString: String = String(format: "%.1f", aFloat) // "1.0"

let wantedString: String = aString.stringByReplacingOccurrencesOfString(".0", withString: "") // "1"
Лео
источник
Это
сломало
@Starceaker Нет, сначала 1.05выполнить String(format: "%.1f", aFloat)будет 1.0, работает. если 1.05выполнить String(format: "%.2f", aFloat)будет 1.05, и чем следует это сделатьstringByReplacingOccurrencesOfString(".00"...)
Лев
Правильно, я сосредоточился на последней строчке. Я думал, вы предложили несколько решений, но на самом деле ваши линии связаны. Виноват.
Starceaker
это ничего :)
Лев