Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

212
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda