How to Evaluate the String Equation in iOS

How to evaluate the string equation in ios

You can use NSExpression for this:

NSExpression *expression = [NSExpression expressionWithFormat:@"1+2"];
NSLog(@"%@", [expression expressionValueWithObject:nil context:nil]);

For further information read the documentation of the used methods.

Swift string formula into a real calculation

Xcode 8.3.1 • Swift 3.1

extension String {
var expression: NSExpression {
return NSExpression(format: self)
}
}

let a = 5
let b = 2
let intDictionary = ["a": a,"b": b]

var formula = "a * b"
if let timesResult = formula.expression.expressionValue(with: intDictionary, context: nil) as? Int {
print(timesResult) // 10
}
formula = "(a + b) / 2"
if let intAvgResult = formula.expression.expressionValue(with: intDictionary, context: nil) as? Int {
print(intAvgResult) // 3
}

let x = 5.0
let y = 2.0
let z = 3.0

let doubleDictionary = ["x": x, "y": y, "z": z]

formula = "(x + y + z) / 3"
if let doubleAvgResult = formula.expression.expressionValue(with: doubleDictionary, context: nil) as? Double {
print(doubleAvgResult)
}

Can you evaluate a string in Swift?

No.

There is no equivalent of eval() in JavaScript or ScriptEngine in Java for Swift.

A common use for string evaluation is mathematical expressions; if you want to evaluate these, you can use NSExpression.valueWithExpression(format: String):

let stringWithMathematicalOperation: String = "5*5" // Example
let exp: NSExpression = NSExpression(format: stringWithMathematicalOperation)
let result: Double = exp.expressionValue(with:nil, context: nil) as! Double // 25.0

Convert NSString of a math equation to a value

Here is an example how to do it with NSPredicate:

NSPredicate *p = [NSPredicate predicateWithFormat:@"1+2==3"];
NSLog(@"%d", [p evaluateWithObject:nil]);
p = [NSPredicate predicateWithFormat:@"1+2==4"];
NSLog(@"%d", [p evaluateWithObject:nil]);

The first NSLog produces 1 because 1+2==3 is true; the second produces 0.

Simple String Equation

When you use an == on pointers like NSString * it is comparing memory addresses, not comparing the value of strings.

Your first example:

if (textfield.text == [textArray objectAtIndex:i])

Is comparing two different memory address. Since they are not the same memory address, the answer is false.

Your second example:

[textArray replaceObjectAtIndex:i withObject:textfield.text];
if (textfield.text == [textArray objectAtIndex:i])

Here you have assigned the memory address of textfield.text into [textArray objectAtIndex:i] thus making them the same memory address. Therefore, the memory addresses are the same so the result is true.

Your last example:

if ([textfield.text isEqualToString:[textArray objectAtIndex:i]])

Is the correct way to evaluate two strings regardless of memory addresses because isEqualToString compares the value of the strings and not their memory addresses.

Hope this helps.

Math evaluation from speech to text

Natural language parsing is a complex task, of course it can be done with simple substring matching or even with regex, but these days there are much more advanced algorithms which use machine learning to classify much more complex situations. Such systems are exemplar-based, that means you can submit them examples and they will learn properly identify intent from them. Such exemplar-based systems could parse things like "multiply the result by three" and understand that the "result" is the previous result and you need to multiply it. They also provide you the parsing confidence

For example of such tool you can check RASA NLU based on SPACY and MITIE, there are also services like LIUS from Microsoft.

It is not easy to run such tools on iOS, you might want to run them on a server over REST API. But compiling MITIE is theoretically possible.

See also

How to proceed with NLP task for recognizing intent and slots

Converting natural language to a math equation

Swift string task

This is a quick implementation: it handles expressions with 2 integer values and a single operator, where the operator is +, -, *, or /. The expressions look like <value> <operator> <value> = <value>. The values on the left-hand side of the expression are integers, but the value on the right-hand side can be a floating point value. (eg try? checkTask(task: "7 / 2 = 3.5") will print OK)

I think it can be a good starting point if you want to do something more advanced.

enum Error: Swift.Error {
case malformed
}
func checkTask(task: String) throws -> String {
let operations = "*/+-"
let split = task.replacingOccurrences(of: " ", with: "").split(separator: "=")
guard let resultString = split.last,
let expressionString = split.first else {
throw Error.malformed
}
let expression = expressionString.split { character in
operations.contains(character)
}

guard let operationString = expressionString.first(where: { operation in operations.contains(operation) }),
let lhsString = expression.first,
let rhsString = expression.last,
let equationResult = Double(String(resultString)),
let lhs = Double(lhsString),
let rhs = Double(rhsString) else {
throw Error.malformed
}

var operation: (Double, Double) -> Double
switch operationString {
case "+":
operation = (+)
case "-":
operation = (-)
case "*":
operation = (*)
case "/":
operation = (/)
default:
throw Error.malformed
}
let result = operation(lhs, rhs)
guard result == equationResult else {
return "Correct answer: \(result)"
}
return "OK"
}
let tasks = ["11 + 14 = 25", "2 + 2 = 5"]
let first = try? checkTask(task: tasks.first!) // "OK"
let second = try? checkTask(task: tasks.last!) // "Correct answer: 4.0"

If you want an error with a description you'll have to make the modifications yourself.



Related Topics



Leave a reply



Submit