Swift duplo para string

108

Antes de atualizar o xCode 6, não tive problemas para converter um double para uma string, mas agora me dá um erro

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

Isso me dá a mensagem de erro "double não é conversível em string". Existe alguma outra maneira de fazer isso?

tim_yng
fonte
5
Também pode ser útil defini-lo comovar b = "\(a)"
erdekhayser

Respostas:

211

Ele não está lançando, está criando uma string a partir de um valor com um formato.

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

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

Com um formato diferente:

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

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

Você também pode omitir a formatpropriedade se nenhuma formatação for necessária.

zaph
fonte
1
Que tal um duplo com um número de dígitos de fração maior? Como let a = 2.34934340320 let stringValue = String (formato: "% f", a) dará 2.349343
Nico
1
A exibição pode ser controlada com as opções de formatação de printf, consulte: Especificadores de formato de string e printf (3) .
zaph
2
Você apenas tem que mudar seu formato para controlar a quantidade de dígitos: format:"%.1f" = 1 digit // 1.5; format:"%.5f" = 5 digits // 1.50000
Megaetron de
3
Por favor, atualize sua resposta, em Swift 2.1 você apenas tem que fazer String(yourDouble).
Alexandre G.
1
Você pode usar let em vez de var. Não há necessidade de ligar várias vezes.
Oleksandr
81
let double = 1.5 
let string = double.description

atualizar o Xcode 7.1 • Swift 2.1:

Agora Double também pode ser convertido em String para que você possa simplesmente usá-lo como desejar:

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

Swift 3 ou posterior , podemos estender LosslessStringConvertiblee torná-lo genérico

Xcode 11.3 • Swift 5.1 ou posterior

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

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

Para um número fixo de dígitos fracionários, podemos estender o FloatingPointprotocolo:

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

Se precisar de mais controle sobre o formato de número (dígitos de fração mínimo e máximo e modo de arredondamento), você pode usar 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"
Leo Dabus
fonte
1
isso é um hack ou é uma maneira legítima de fazer isso? isso causaria problemas com as diferentes versões do ios?
Esqarrouth
2
Não, você não terá problemas com as diferentes versões do ios. Também funciona para OSX. BTW, isso é o que você obtém ao fazer interpolação de string com um duplo ou um int.
Leo Dabus
Muito útil. Você não pode formatar como% f. E funciona também para Int, então você tem uma maneira de fazer isso para dois tipos.
Patrik Vaberer,
Isso não funcionará para 0,00001, ele se tornará "1e-05" como uma string.
Alex
Substituir String(format: "%.\(digits)f", self as! CVarArg)porString(format: "%.*f", digits, self as! CVarArg)
rmaddy
21

Além da resposta @Zaph, você pode criar extension:

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

Uso:

var a:Double = 1.5
println("output: \(a.toString())")  // output: 1.5
Maxim Shoustin
fonte
1
@MaximShoustin O OP não tem representantes suficientes para votar e responder, 15 são necessários. Também discordo da criação de uma Extensão, quando a frase: a.toString()for vista por outro desenvolvedor definitivamente haverá um momento WTF.
zaph
1
@Zaph porque não. Com certeza você pode adicionar algum prefixo e alterá-lo myToString()para ter certeza de que sua definição personalizada. Mas, como em outras linguagens, a prototipagem evita a duplicação de código e uma boa manutenção.
Maxim Shoustin de
@MaximShoustin newbie question: qual é a diferença entre println("output: \(a.toString())")e println("output: \(a)"). A segunda opção não causa erros de compilação. Esta opção é uma má prática?
Alex Guerrero
Existe uma maneira inteligente de escrever tal extensão para Double ou FloatingPoint que funcionaria em um Optional Double para retornar uma String vazia?
Kinergy 01 de
@KinergyyourDouble?.toString() ?? ""
Leo Dabus
11

Swift 3+: experimente estas linhas de código

let num: Double = 1.5

let str = String(format: "%.2f", num)
Shiv Kumar
fonte
9

para transformar qualquer coisa em uma string em swift, exceto talvez valores de enum, simplesmente faça o que você faz no método println ()

por exemplo:

var stringOfDBL = "\(myDouble)"
Eric Bob
fonte
3

Swift 4 : use o seguinte código

let number = 2.4
let string = String(format: "%.2f", number)
Abhishek Jain
fonte
1
É a mesma solução dada por @ shiv-kumar stackoverflow.com/a/46487485/2227743
Eric Aya
3

Esta função permitirá que você especifique o número de casas decimais a serem mostradas:

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

Uso:

let numberString = doubleToStringDecimalPlacesWithDouble(number: x, numberOfDecimalPlaces: 2)
MobileMon
fonte
Substitua String(format:"%."+numberOfDecimalPlaces.description+"f", number)porString(format:"%.*f", numberOfDecimalPlaces, number)
rmaddy
3

Existem muitas respostas aqui que sugerem uma variedade de técnicas. Mas ao apresentar números na IU, você invariavelmente deseja usar um NumberFormatterpara que os resultados sejam formatados, arredondados e localizados corretamente:

let value = 10000.5

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

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

Se você quiser um número fixo de casas decimais, por exemplo, para valores monetários

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

Mas a beleza dessa abordagem é que ela será adequadamente localizada, resultando nos 10,000.50Estados Unidos, mas 10.000,50na Alemanha. Localidades diferentes têm formatos preferenciais diferentes para números e devemos permitir o NumberFormatteruso do formato preferido pelo usuário final ao apresentar valores numéricos na IU.

Desnecessário dizer que, embora NumberFormatterseja essencial ao preparar representações de string dentro da IU, não deve ser usado se estiver escrevendo valores numéricos como strings para armazenamento persistente, interface com serviços da web, etc.

Roubar
fonte
2
Esta deve ser marcada como a resposta certa
Asad Khan
2

Em swift 3:

var a: Double = 1.5
var b: String = String(a)
Carlson
fonte
1

No Swift 3 é simples, conforme mostrado abaixo

let stringDouble =  String(describing: double)
Sebin Roy
fonte
3
Isso retorna, por exemplo, "Optional(6.1696108999999995)"para mim.
McSullivan D'Ander
0
var b = String(stringInterpolationSegment: a)

Isso funciona para mim. Você pode tentar

sevenkplus
fonte
0

No Swift 4, se você quiser modificar e usar um Double na IU como um textLabel "String", você pode adicionar isso no final do seu arquivo:

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

}

E use-o assim se quiser que seja em um rótulo de texto:

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

Ou imprima-o como um Int:

print(weatherData.tempCelsius.roundToInt())
Patrik Rikama-Hinnenberg
fonte
0

Eu preferiria a abordagem NSNumber e NumberFormatter (quando necessário), também você pode usar a extensão para evitar o inchaço do código

extension Double {

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

}

Você também pode precisar de abordagem reversa

extension String {

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

}
Giuseppe Mazzilli
fonte
por que você está retornando opcional, mas atribuindo .nan se nulo? Você deve fazer um ou outro. Não ambos. Btw O que há de errado em usar o inicializador de String? Você também pode torná-lo mais genérico, estendendo o LossLessStringConvertibleprotocolo em vez de estender Duplo extension LosslessStringConvertible { var string: String { return .init(self) } }
Leo Dabus
Você está certo devolvendo o dobro? É uma recusa pois já verifiquei que é nulo e volto NaN
Giuseppe Mazzilli
0

Swift 5 : use o seguinte código

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)
    }
}
g212gs
fonte
Substitua String(format: "%.\(points)f", self)porString(format: "%.*f", points, self)
rmaddy