Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to format decimal in Swift to percentage

I have a function which finds percentage difference of adjacent values in an array.

var values =  [1.623,1.614,1.591,1.577,1.600,1.579,1.622]
values.reverse()
let percentages = [0] + zip(values, values.dropFirst()).map { (old, new) in
    return (100.0 * (new - old) / old)
}
print(percentages)

[0.0, -2.651048088779294, 1.3299556681444034, -1.4375000000000082, 0.8877615726062151, 1.445631678189826, 0.5576208178438598]

Is there a way i can format my values to look like the below

["+0.006%","+0.014%","+0.009%","-0.014%","+0.013%","-0.027%"]

like image 540
BigFire Avatar asked Aug 22 '19 23:08

BigFire


1 Answers

You could start with a NumberFormatter, for example...

let formatter = NumberFormatter()
formatter.numberStyle = .percent
formatter.minimumIntegerDigits = 1
formatter.maximumIntegerDigits = 1
formatter.maximumFractionDigits = 3

var values =  [1.623,1.614,1.591,1.577,1.600,1.579,1.622]
values.reverse()
let percentages = [0] + zip(values, values.dropFirst()).map {
    (old, new) in
    return (100.0 * (new - old) / old)
}

print(percentages.compactMap { formatter.string(from: NSNumber(value: $0 / 100.0)) })

which will print something like....

["0%", "-2.651%", "1.33%", "-1.438%", "0.888%", "1.446%", "0.558%"]

Your string only shows the signal for negative numbers. This is not what OP asked.

🙄 Heaven forbid the OP might actually have to do "some" work 🤣😉

print(percentages.map { ($0 >= 0 ? "+" : "") + formatter.string(for: $0 / 100.0)! })

Or, preferably...

formatter.positivePrefix = "+"
//....
print(percentages.compactMap { formatter.string(for: $0 / 100.0) })

which prints...

["+0%", "-2.651%", "+1.33%", "-1.438%", "+0.888%", "+1.446%", "+0.558%"]

can you explain a little further if possible with example how the numbers can be fudged?

The format of the value doesn't seem to match the value your are producing, for example, 0.8877615726062151 would be 0.8%, not 0.009%, so you have a slight customisation, which would best accomplished by "fudging" the values slightly.

So, again, starting with...

let formatter = NumberFormatter()
formatter.numberStyle = .percent
formatter.minimumIntegerDigits = 1
formatter.maximumIntegerDigits = 1
formatter.maximumFractionDigits = 3
formatter.minimumFractionDigits = 3
formatter.positivePrefix = "+"

I modified

print(percentages.compactMap { formatter.string(for: $0 / 100.0) })

to

print(percentages.compactMap { formatter.string(for: $0 / 10000.0) })

which now prints

["+0.000%", "-0.027%", "+0.013%", "-0.014%", "+0.009%", "+0.014%", "+0.006%"]

which based on my observations, seems to be what you're aiming for - you just get localisation for free

like image 110
MadProgrammer Avatar answered Oct 22 '22 04:10

MadProgrammer