Swift double to string


108

До того, как я обновил xCode 6, у меня не было проблем с приведением двойника к строке, но теперь это дает мне ошибку

var a: Double = 1.5
var b: String = String(a)

Это дает мне сообщение об ошибке «double не преобразовывается в строку». Есть ли другой способ сделать это?


5
Также может быть полезно просто определить это какvar b = "\(a)"
erdekhayser

Ответы:


212

Это не приведение, это создание строки из значения с форматом.

let a: Double = 1.5
let b: String = String(format: "%f", a)

print("b: \(b)") // b: 1.500000

В другом формате:

let c: String = String(format: "%.1f", a)

print("c: \(c)") // c: 1.5

Вы также можете опустить formatсвойство, если форматирование не требуется.


1
А как насчет двойника с большим числом десятичных разрядов? Например, let a = 2.34934340320 let stringValue = String (format: "% f", a) даст 2.349343
Нико

1
Отображением можно управлять с помощью параметров форматирования printf, см. Спецификаторы строкового формата и printf (3) .
zaph

2
Вы просто должны изменить свой формат , чтобы контролировать количество цифр: format:"%.1f" = 1 digit // 1.5; format:"%.5f" = 5 digits // 1.50000
Megaetron 09

3
Обновите свой ответ, в Swift 2.1 вам просто нужно это сделать String(yourDouble).
Александр Г.

1
Вы можете использовать let вместо var. Теперь нет необходимости звонить по несколько раз.
Александр

82
let double = 1.5 
let string = double.description

обновить Xcode 7.1 • Swift 2.1:

Теперь Double также можно преобразовать в String, поэтому вы можете просто использовать его по своему усмотрению:

let double = 1.5
let doubleString = String(double)   // "1.5"

Swift 3 или новее мы можем расширить LosslessStringConvertibleи сделать его универсальным

Xcode 11.3 • Swift 5.1 или новее

extension LosslessStringConvertible { 
    var string: String { .init(self) } 
}

let double = 1.5 
let string = double.string  //  "1.5"

Для фиксированного количества цифр дроби мы можем расширить FloatingPointпротокол:

extension FloatingPoint {
    func fixedFraction(digits: Int) -> String {
        return String(format: "%.*f", digits, self as! CVarArg)
    }
}

Если вам нужен больший контроль над форматом чисел (минимальные и максимальные цифры дробной части и режим округления), вы можете использовать NumberFormatter:

extension Formatter {
    static let number = NumberFormatter()
}

extension FloatingPoint {
    func fractionDigits(min: Int = 2, max: Int = 2, roundingMode: NumberFormatter.RoundingMode = .halfEven) -> String {
        Formatter.number.minimumFractionDigits = min
        Formatter.number.maximumFractionDigits = max
        Formatter.number.roundingMode = roundingMode
        Formatter.number.numberStyle = .decimal
        return Formatter.number.string(for: self) ?? ""
    }
}

2.12345.fractionDigits()                                    // "2.12"
2.12345.fractionDigits(min: 3, max: 3, roundingMode: .up)   // "2.124"

1
это взлом или это законный способ сделать это? это вызовет проблемы с разными версиями ios?
Esqarrouth

2
Нет, с разными версиями ios проблем не возникнет. Это также работает для OSX. Кстати, это то, что вы получаете при выполнении строковой интерполяции с помощью Double или Int.
Лео Дабус

Очень полезно. Вы не можете форматировать как% f. И это также работает для Int, поэтому у вас есть один способ сделать это для двух типов.
Патрик Ваберер

Это не сработает для 0,00001, оно становится строкой «1e-05».
Alex

Заменить String(format: "%.\(digits)f", self as! CVarArg)наString(format: "%.*f", digits, self as! CVarArg)
rmaddy

21

В дополнение к ответу @Zaph вы можете создать extension:

extension Double {
    func toString() -> String {
        return String(format: "%.1f",self)
    }
}

Использование:

var a:Double = 1.5
println("output: \(a.toString())")  // output: 1.5

1
@MaximShoustin У OP недостаточно представителей, чтобы проголосовать и ответить, требуется 15. Я также не согласен с созданием расширения, когда утверждение: a.toString()увидит другой разработчик, определенно будет момент WTF.
zaph

1
@Zaph, почему бы и нет. Конечно, вы можете добавить какой-нибудь префикс и изменить его, чтобы myToString()убедиться, что его собственное определение. Но, как и в случае с другими языками, создание прототипов позволяет избежать дублирования кода и обеспечить хорошее обслуживание.
Максим Шустин

@MaximShoustin вопрос для новичков: в чем разница между println("output: \(a.toString())")и println("output: \(a)"). Второй вариант не вызывает ошибок компиляции. Это плохая практика?
Alex Guerrero

Есть ли умный способ написать такое расширение для Double или FloatingPoint, которое работало бы с Optional Double и возвращало бы пустую строку?
Kinergy 01

@KinergyyourDouble?.toString() ?? ""
Лео Дабус


9

чтобы сделать что-либо строкой в ​​swift, кроме, возможно, значений enum, просто делайте то, что вы делаете в методе println ()

например:

var stringOfDBL = "\(myDouble)"


3

Эта функция позволит вам указать количество отображаемых десятичных знаков:

func doubleToString(number:Double, numberOfDecimalPlaces:Int) -> String {
    return String(format:"%."+numberOfDecimalPlaces.description+"f", number)
}

Использование:

let numberString = doubleToStringDecimalPlacesWithDouble(number: x, numberOfDecimalPlaces: 2)

Заменить String(format:"%."+numberOfDecimalPlaces.description+"f", number)наString(format:"%.*f", numberOfDecimalPlaces, number)
rmaddy

3

Здесь есть много ответов, предлагающих самые разные методы. Но при представлении чисел в пользовательском интерфейсе вы всегда хотите использовать, NumberFormatterчтобы результаты были правильно отформатированы, округлены и локализованы:

let value = 10000.5

let formatter = NumberFormatter()
formatter.numberStyle = .decimal

guard let string = formatter.string(for: value) else { return }
print(string) // 10,000.5

Если вам нужно фиксированное количество десятичных знаков, например, для денежных значений

let value = 10000.5

let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2

guard let string = formatter.string(for: value) else { return }
print(string) // 10,000.50

Но прелесть этого подхода в том, что он будет правильно локализован, в результате чего в 10,000.50США будет 10.000,50Германия. В разных регионах используются разные предпочтительные форматы чисел, и мы должны позволить NumberFormatterиспользовать формат, предпочитаемый конечным пользователем, при представлении числовых значений в пользовательском интерфейсе.

Излишне говорить, что, хотя NumberFormatterэто важно при подготовке строковых представлений в пользовательском интерфейсе, его не следует использовать при записи числовых значений в виде строк для постоянного хранения, интерфейса с веб-службами и т. Д.


2
Это следует отметить как правильный ответ
Асад Хан


1

В Swift 3 это просто, как показано ниже

let stringDouble =  String(describing: double)

3
Это возвращается, например, "Optional(6.1696108999999995)"для меня.
McSullivan D'Ander

0
var b = String(stringInterpolationSegment: a)

У меня это работает. Вы можете попробовать


0

В Swift 4, если вы хотите изменить и использовать Double в пользовательском интерфейсе в качестве textLabel «String», вы можете добавить это в конец файла:

    extension Double {
func roundToInt() -> Int{
    return Int(Darwin.round(self))
}

}

И используйте это так, если хотите, чтобы это было в текстовой метке:

currentTemp.text = "\(weatherData.tempCelsius.roundToInt())"

Или распечатайте его как Int:

print(weatherData.tempCelsius.roundToInt())

0

Я бы предпочел подход NSNumber и NumberFormatter (где необходимо), также вы можете использовать расширение, чтобы избежать раздувания кода

extension Double {

   var toString: String {
      return NSNumber(value: self).stringValue
   }

}

U может также потребоваться обратный подход

extension String {

    var toDouble: Double {
        return Double(self) ?? .nan
    }

}

почему вы возвращаете необязательный, но назначаете .nan, если ноль? Вы должны сделать либо то, либо другое. Не оба. Кстати, что не так с использованием инициализатора String? Вы также можете сделать его более общим LossLessStringConvertibleпротоколом расширения вместо расширения Double extension LosslessStringConvertible { var string: String { return .init(self) } }
Лео Дабус

Вы правы возвращаете Дабл? Это отказ, поскольку я уже проверял, что он равен нулю, и возвращаю NaN
Джузеппе

0

Swift 5 : используйте следующий код

extension Double {

    func getStringValue(withFloatingPoints points: Int = 0) -> String {
        let valDouble = modf(self)
        let fractionalVal = (valDouble.1)
        if fractionalVal > 0 {
            return String(format: "%.*f", points, self)
        }
        return String(format: "%.0f", self)
    }
}

Заменить String(format: "%.\(points)f", self)наString(format: "%.*f", points, self)
rmaddy
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.