我可以强制 NSExpression 和 expressionValue 以某种方式采用双精度数而不是整数吗?

Bea*_*ley 4 math nsexpression swift

我正在尝试从字符串中进行数学计算。

当我使用 NSExpression 将字符串转换为数学问题,然后使用 expressionValue 获取结果时,Swift 假设我想要一个整数。考虑这两个 Playground 示例:

let currentCalculation = "10 / 6"
let currentExpression = NSExpression(format: currentCalculation)
print(currentExpression) // 10 / 6
if let result = currentExpression.expressionValue(with: nil, context: nil) as? Double {
    print(result) // 1
}

let anotherCalculation = "10.0 / 6.0"
let anotherExpression = NSExpression(format: anotherCalculation)
print(anotherExpression) // 10 / 6
if let result = anotherExpression.expressionValue(with: nil, context: nil) as? Double {
    print(result) // 1.666666667
}
Run Code Online (Sandbox Code Playgroud)

我应该怎么做才能始终获得双倍结果?我不想提前解析字符串。

非常有趣的是,第二个示例将“anotherExpression”转换为整数,但仍然返回 Double 作为结果。

Mar*_*n R 5

您可能最好使用第三方表达式解析器/评估器,例如DDMathParserNSExpression非常有限,并且没有强制浮点计算的选项。

如果您想(或必须)坚持NSExpression:以下是一种可能的解决方案,可以(递归地)用浮点值替换表达式中的所有常量值:

extension NSExpression {

    func toFloatingPoint() -> NSExpression {
        switch expressionType {
        case .constantValue:
            if let value = constantValue as? NSNumber {
                return NSExpression(forConstantValue: NSNumber(value: value.doubleValue))
            }
        case .function:
           let newArgs = arguments.map { $0.map { $0.toFloatingPoint() } }
           return NSExpression(forFunction: operand, selectorName: function, arguments: newArgs)
        case .conditional:
           return NSExpression(forConditional: predicate, trueExpression: self.true.toFloatingPoint(), falseExpression: self.false.toFloatingPoint())
        case .unionSet:
            return NSExpression(forUnionSet: left.toFloatingPoint(), with: right.toFloatingPoint())
        case .intersectSet:
            return NSExpression(forIntersectSet: left.toFloatingPoint(), with: right.toFloatingPoint())
        case .minusSet:
            return NSExpression(forMinusSet: left.toFloatingPoint(), with: right.toFloatingPoint())
        case .subquery:
            if let subQuery = collection as? NSExpression {
                return NSExpression(forSubquery: subQuery.toFloatingPoint(), usingIteratorVariable: variable, predicate: predicate)
            }
        case .aggregate:
            if let subExpressions = collection as? [NSExpression] {
                return NSExpression(forAggregate: subExpressions.map { $0.toFloatingPoint() })
            }
        case .anyKey:
            fatalError("anyKey not yet implemented")
        case .block:
            fatalError("block not yet implemented")
        case .evaluatedObject, .variable, .keyPath:
            break // Nothing to do here
        }
        return self
    }
}
Run Code Online (Sandbox Code Playgroud)

例子:

let expression = NSExpression(format: "10/6+3/4")
if let result = expression.toFloatingPoint().expressionValue(with: nil, context: nil) as? Double {
    print("result:", result) // 2.41666666666667
}
Run Code Online (Sandbox Code Playgroud)

这适用于使用算术运算符和函数的“简单”表达式以及一些“高级”表达式类型(并集、交集……)。如有必要,可以添加剩余的转换。