Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

211
Views
Swift pierde precisión en el formato decimal

Tengo un problema de precisión al tratar con la entrada de moneda usando el tipo Decimal. El problema es con el formateador. Este es el código mínimo reproducible en el patio de recreo:

 let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.isLenient = true formatter.maximumFractionDigits = 2 formatter.generatesDecimalNumbers = true let text = "89806.9" let decimal = formatter.number(from: text)?.decimalValue ?? .zero let string = "\(decimal)" print(string)

Imprime 89806.89999999999 en lugar de 89806.9 . Sin embargo, la mayoría de los otros números están bien (por ejemplo 8980.9 ). Así que no creo que este sea un problema de doble vs decimal.

Editar:

La razón por la que necesito usar el formateador es que a veces necesito lidiar con la entrada de formato de moneda:

 let text = "$89,806.9" let decimal = formatter.number(from: text)?.decimalValue ?? .zero print("\(decimal)") // prints 89806.89999999999 let text2 = "$89,806.9" let decimal2 = Decimal(string: text2) print("\(decimal2)") // prints nil
over 4 years ago · Santiago Trujillo
4 answers
Answer question

0

Estoy de acuerdo en que este es un error sorprendente, y abriría un comentario de Apple al respecto, pero también recomendaría cambiar a Decimal(string:locale:) en lugar de un formateador, que logrará su objetivo (excepto quizás la parte isLenient ).

 let x = Decimal(string: text)! print("\(x)") // 89806.9

Si desea corregir los dígitos de las fracciones, puede aplicar el redondeo con bastante facilidad con conversiones * 100 / 100 100/100 a través de Int. (Explicaré si no es obvio cómo hacer esto; funciona para Decimal, aunque no para Double).

over 4 years ago · Santiago Trujillo Report

0

Si esto es estrictamente un problema de representación y solo está buscando traducir un valor de moneda de una cadena sin procesar a una cadena formateada, simplemente hágalo.

 let formatter = NumberFormatter() formatter.numberStyle = .currency let raw = "89806.9" if let double = Double(raw), let currency = formatter.string(from: NSNumber(value: double)) { print(currency) // $89,806.90 }

Si hay matemáticas involucradas, entonces, antes de usar los formateadores de cadenas, le indicaría ¿ Por qué no usar Double o Float para representar la moneda? y Cómo redondear un doble a un int utilizando Banker's Rounding in C como excelentes puntos de partida.

over 4 years ago · Santiago Trujillo Report

0

Usar el nuevo FormatStyle parece generar el resultado correcto

 let format = Decimal.FormatStyle .number .precision(.fractionLength(0...2)) let text = "89806.9" let value = try! format.parseStrategy.parse(text)

A continuación se muestra un ejemplo de análisis de una moneda utilizando el código de moneda de la configuración regional

 let currencyFormat = Decimal.FormatStyle.Currency .currency(code: Locale.current.currencyCode!) .precision(.fractionLength(0...2)) let amount = try! currencyFormat.parseStrategy.parse(text)

Ejemplo sueco:

 let text = "89806,9 kr" print(amount)

89806.9

Otra opción es usar el nuevo init para Decimal que toma una Cadena y un FormatStyle.Currency (o un Número o Porcentaje)

 let amount = try Decimal(text, format: currencyFormat)

y para formatear este valor podemos usar formatted(_:) en Decimal

 print(amount.formatted(currencyFormat))

Salida (todavía sueco):

89 806,9 €

over 4 years ago · Santiago Trujillo Report

0

Recibo mi respuesta con valor doble y elimino la línea formatter.generatesDecimalNumbers para que funcione.

 let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.isLenient = true formatter.maximumFractionDigits = 2 //formatter.generatesDecimalNumbers = true // I removed this line let text = "$89806.9" let double = formatter.number(from: text)?.doubleValue ?? .zero // converting as double or float let string = "\(double)" print(string) // 89806.9 let anotherText = "$0.1" let anotherDouble = formatter.number(from: anotherText)?.doubleValue ?? .zero // converting as double or float let anotherString = "\(anotherDouble)" print(anotherString) // 0.1
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!