Maury Markowitz
Maury Markowitz

Reputation: 9293

NSNumberFormatter only display "E" for large/small values?

I have an NSTableView that I populate with numbers. These are often numbers like "1" or "15" that I can display normally. However, a subset of them are always very large or small, like "1.5E8".

I made an NSNumberFormatter singleton so I could use stringFromNumber to format these, but it seems that I can only have E on or off:

enter image description here

Those "0E0"'s are useless, they should simply be "0". There doesn't seem to be a setting for this though. Am I just missing something?

Or do you always have to do this in code?

Here is the setup code in my document subclass:

var measurementFormatter: NSNumberFormatter = NSNumberFormatter()
measurementFormatter.locale = NSLocale.currentLocale()
measurementFormatter.numberStyle = .ScientificStyle
measurementFormatter.alwaysShowsDecimalSeparator = true
measurementFormatter.minimumFractionDigits = 0
measurementFormatter.maximumFractionDigits = 6
measurementFormatter.generatesDecimalNumbers = false

And an example use:

numStr = (document?.measurementFormatter.stringFromNumber(num)!

Upvotes: 1

Views: 230

Answers (1)

Code Different
Code Different

Reputation: 93191

I don't claim to be an NSNumberFormatter expert - there are too many options to remember. But setting zeroSymbol seems to solve your problem:

measurementFormatter.zeroSymbol = "0"

Edit: I have spent too much time over this tonight. It seems like there no way to get rid of those E0, so I decided to subclass NSNumberFormatter instead:

class MyNumberFormatter: NSNumberFormatter {
    override func stringFromNumber(number: NSNumber) -> String? {
        guard let str = super.stringFromNumber(number) else {
            return nil
        }
        return str.stringByReplacingOccurrencesOfString("E0", withString: "", options: [.AnchoredSearch, .BackwardsSearch], range: str.startIndex..<str.endIndex)
    }
}

var measurementFormatter = MyNumberFormatter()
measurementFormatter.locale = NSLocale.currentLocale()
measurementFormatter.numberStyle = .ScientificStyle
measurementFormatter.alwaysShowsDecimalSeparator = true
measurementFormatter.minimumFractionDigits = 0
measurementFormatter.maximumFractionDigits = 6
measurementFormatter.generatesDecimalNumbers = false

// Examples:
[0, 0.0014, 2, 15, 3.14, 100, 1500000000].forEach {
    print("\($0) --> \(measurementFormatter.stringFromNumber($0)!)")
}

Output:

0 --> 0
0.0014 --> 1.4E-3
2 --> 2
15 --> 1.5E1
3.14 --> 3.14
100 --> 1E2
1500000000 --> 1.5E9

Upvotes: 1

Related Questions