cs193p – Assignment #1 Extra Task #2

cs193p-assignment-1-extra-task-2-winter-2017

Figure out from the documentation how to use the iOS struct NumberFormatter to format your display so that it only shows 6 digits after the decimal point (instead of showing all digits that can be represented in a Double). This will eliminate (or at least reduce) the need for Autoshrink in your display. While you’re at it, make it so that numbers that are integers don’t have an unnecessary “.0” attached to them (e.g. show “4” rather than “4.0” as the result of the square root of sixteen). You can do all this for your description in the CalculatorBrain as well.

First of all, the last task had a tiny bug. when entering e.g. “0,” will show a leading zero:

    @IBAction func backSpace(_ sender: UIButton) {
            ...
            if text.isEmpty || "0" == text {
                ...
    }

Using the number formatter means that numbers will use the the international number format of the device. Thus the decimal separator could not only be “.” but also “.”.

Create an outlet for the comma button, and use the number formatter to change its label to the the correct comma separator symbol:

    @IBOutlet weak var decimalSeparatorButton: UIButton!

    private let decimalSeparator = NumberFormatter().decimalSeparator!

    override func viewDidLoad() {
        ...
        decimalSeparatorButton.setTitle(decimalSeparator, for: .normal);
    }

Wherever we hard coded the dot, this needs to change to use the correct decimal separator symbol:

    @IBAction func touchDigit(_ sender: UIButton) {
            ...
            if decimalSeparator != digit 
            || !textCurrentlyInDisplay.contains(decimalSeparator) {
                ...
            case decimalSeparator:
                display.text = "0" + decimalSeparator
            ...
    }

If the decimal separator is a “,” this would break the current code to get a double value from the display. Thus we need to use the number formatter here as well:

    var displayValue: Double {
        get {
            return (NumberFormatter().number(from: display.text!)?.doubleValue)!
        }
        ...
    }

For the other direction (the output), adjust the the beautify method. Find the numbers in the string and replace them with the formatted string. The tricky part here is to translate between string and NSString for the various methods:

extension String {
    static let DecimalDigits = 6
    
    func beautifyNumbers() -> String {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.maximumFractionDigits = String.DecimalDigits

        var text = self as NSString
        var numbers = [String]()
        let regex = try! NSRegularExpression(pattern: "[.0-9]+", options: .caseInsensitive)
        let matches = regex.matches(in: self, options: [], range: NSMakeRange(0, text.length))
        numbers = matches.map { text.substring(with: $0.range) }
        
        for number in numbers {
            text = text.replacingOccurrences(
                of: number,
                with: formatter.string(from: NSNumber(value: Double(number)!))!
            ) as NSString
        }
        return text as String;
    }
}

The complete code for the assignment #1 extra task #2 is available on GitHub.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

Leave a Reply

Your email address will not be published.