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?


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.


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"

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

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)

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


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)

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.


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)

1

No Swift 3 é simples, conforme mostrado abaixo

let stringDouble =  String(describing: double)

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


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

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
    }

}

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

Substitua String(format: "%.\(points)f", self)porString(format: "%.*f", points, self)
rmaddy
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.