Search code examples
swiftnsnumberformatter

No scientific notation and rounding with double


I want to round a number to 6 places and I don't want it to be displayed using scientific notation. I am using this code to round the decimal to 6 places but if the value is really small, it is still displaying it using scientific notation. I know that I can use the number formatter (displayed below as well) to remove the scientific notation but if I do that then it is returns a string so I cannot round a string to a certain number of decimal places. If I do the rounding first, that still doesn't work in all scenarios. It still shows some numbers without rounding. What is the best way to achieve this? It should work in all different scenarios where numbers are infinitely long or repeating

extension Double {
    // Rounds the double to decimal places value
    func rounded(toPlaces places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
       return (self * divisor).rounded() / divisor
    }
}




let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = NumberFormatter.Style.decimal
numberFormatter.number(from:"")

I tried to use this code

let currentValue = 1/2.3344 //answer is 0.42837559972584...
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = NumberFormatter.Style.decimal
numberFormatter.maximumFractionDigits = 6
guard let finalNum = numberFormatter.number(from: String(describing: currentValue)) else {return nil}
text = String (describing: finalNum)

I want it to display 0.428375. The value rounded to 6 decimal places.

When the current value is this: let currentValue = 1/233442 which is 0.00000428371... I want it to display 0.000004. The decimal rounded to 6 decimal places and not in scientific notation.

When the current value is this: let currentValue = 1/2334429 I want it to display 0 because that is the value rounded to 6 decimal places.


Solution

  • The number(from: someString) method converts a string to a number, you want it the other way around:

    let currentEntry = 1/2.3344
    
    let numberFormatter = NumberFormatter()
    numberFormatter.numberStyle = .decimal
    numberFormatter.maximumFractionDigits = 6
    
    guard let text = numberFormatter.string(for: currentEntry) else {
        // ...
    }
    print(text) // 0.428376
    

    Note that your String(describing:) conversions only hide the problem. You really should avoid String(describing:) (even if the compiler suggests it as a Fix-it!), it almost never does what you need.