1

I'm trying to solve mathematical expressions using NSPredicate and NSExpression.

In case the expression is entered with floating-points at every operand the calculation gets solved correctly.

Expressions, where floating points are missing for some operands, results may be wrong.

To show you what I tried already here is my playgrounds code within i'm testing.

Broken

The calculation of 5 * (5/2) should result in 12.5, but the expression gives me a result of 10.0, because it calculates 5 * 2

let input1 = "5*(5/2)" // == 10.0, should be 12.5

let predicate1 = NSPredicate(format: "1.0 * \(input1) = 0")

if let comparisation = predicate1 as? NSComparisonPredicate {
    let leftExpression = comparisation.leftExpression

    if let result = leftExpression.expressionValue(with: nil, 
                                                context: nil) as? NSNumber {
        print("Result is: \(result.doubleValue)") // == 10.0
    }
}

Workaround

To show you that calculating by using NSExpression does actually work, here is my current work around to fix the above result.

let input2 = "5*(5.0/2.0)" // == 12.5

let predicate2 = NSPredicate(format: "1.0 * \(input2) = 0")

if let comparisation = predicate2 as? NSComparisonPredicate {
    let leftExpression = comparisation.leftExpression

    if let result = leftExpression.expressionValue(with: nil, 
                                                context: nil) as? NSNumber {
        print("Result is: \(result.doubleValue)") // == 12.5
    }
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
regetskcob
  • 1,172
  • 1
  • 13
  • 35
  • This looks to be the intended behaviour. – EmptyStack Nov 13 '17 at 09:41
  • @EmptyStack are there docs which mention this as intended? – regetskcob Nov 13 '17 at 09:43
  • 1
    That has been observed before: https://stackoverflow.com/q/41455572/1187415, https://stackoverflow.com/q/14346056/1187415, https://stackoverflow.com/q/46550658/1187415 – Martin R Nov 13 '17 at 09:47
  • @MartinR thanks for the both links! One is not helpful for complex formulars, but the other one seems the solution. So my workaround above is already the intended way to solve this... – regetskcob Nov 13 '17 at 09:50
  • @MartinR But why is '5*5/2' (without rounded brackets) correctly solved? – regetskcob Nov 13 '17 at 10:08
  • Then your expression becomes "1.0 * 5*5/2", which is evaluated from left to right. – Martin R Nov 13 '17 at 10:23
  • My guess is `5/2` was interpreted as an integer division, by which 2 is the expected outcome. Your second solution worked because it recasted this into a floating point division – Code Different Nov 13 '17 at 15:07

0 Answers0