NSExpression Calculator in Swift

As already said in a comment, you have to call expressionValueWithObject() on the expression:

let expr = NSExpression(format: equation)
if let result = expr.expressionValueWithObject(nil, context: nil) as? NSNumber {
    let x = result.doubleValue
    println(x)
} else {
    println("failed")
}

Update for Swift 3:

let expr = NSExpression(format: equation)
if let result = expr.expressionValue(with: nil, context: nil) as? Double {
    print(result) // -0.25
} else {
    print("failed")
}

Details

  • Xcode 9.4.1, Swift 4.1
  • Xcode 10.2.1 (10E1001), Swift 5

Solution

import Foundation

extension String {

    private func allNumsToDouble() -> String {

        let symbolsCharSet = ".,"
        let fullCharSet = "0123456789" + symbolsCharSet
        var i = 0
        var result = ""
        var chars = Array(self)
        while i < chars.count {
            if fullCharSet.contains(chars[i]) {
                var numString = String(chars[i])
                i += 1
                loop: while i < chars.count {
                    if fullCharSet.contains(chars[i]) {
                        numString += String(chars[i])
                        i += 1
                    } else {
                        break loop
                    }
                }
                if let num = Double(numString) {
                    result += "\(num)"
                } else {
                    result += numString
                }
            } else {
                result += String(chars[i])
                i += 1
            }
        }
        return result
    }

    func calculate() -> Double? {
        let transformedString = allNumsToDouble()
        let expr = NSExpression(format: transformedString)
        return expr.expressionValue(with: nil, context: nil) as? Double
    }
}

Usage

"3*(3-1)-5".calculate()

Full sample

    func test(_ expressrion: String) {
    if let num = expressrion.calculate() {
        print("\(expressrion) = \(num)")
    } else {
        print("\(expressrion) = nil")
    }
}

test("3*(3-1)-5")
test("5.2*(2-1.79)-5.1")
test("11/5")

Results

enter image description here