NSExpression 1/2

Posted

技术标签:

【中文标题】NSExpression 1/2【英文标题】: 【发布时间】:2013-01-15 20:14:33 【问题描述】:

我想计算一个字符串,我正在这样做:

NSExpression *expression = [NSExpression expressionWithFormat:calculationString];
float result = [[expression expressionValueWithObject:nil context:nil] floatValue];
NSLog(@"%f", result);

问题是,当计算字符串为 1/2 时,结果为 0。我尝试将 float 与 double 和 NSNumber 以及 %f 更改为 %f 和 %@,但我总是得到 0。我有什么改变?

另外,如果重要的话,我在欧洲,所以我有逗号而不是这个值的点,但这应该没关系,因为我用 %f 记录它,它显示为点。仅供参考

【问题讨论】:

【参考方案1】:

基本上,你只需要告诉它你正在执行浮点运算,

1.0/2
1.0/2.0
1/2.0

一切正常

【讨论】:

这应该被标记为正确答案【参考方案2】:

输入NSExpression 很像在C 中:看起来像整数(无小数点/逗号)的文字被视为整数,因此使用整数除法。 (在整数除法下,1/2 0。如果要 0.5,则需要浮点除法。)在解析和评估表达式时会发生这种情况,因此尝试更改结果的类型或输出的格式没有影响——这些事情发生在解析和评估之后。

如果您的calculationString 完全在您的控制之下,那么很容易确保您在任何需要浮点除法的地方使用浮点文字。 (也就是说,使用1.0/2 而不是1/2。)如果没有,你需要改变它,这样它就可以了——这里最好分解解析的NSExpression 并更改一个操作数而不是修改字符串。


“分解”位的后续编辑:您知道具有高阶结构的内容中的字符串转换通常是problematic。使用NSExpression,您已经有了一个解析器(它比简单的正则表达式更聪明)为您分解字符串——这实际上就是NSExpression 的全部意义所在。

因此,如果您使用的是用户提供的字符串,请不要尝试通过更改字符串来更改表达式。让NSExpression 解析它,然后使用结果对象的属性将其分离成其组成表达式。如果您的字符串只是“1/2”,那么您的表达式有一个由两个 arguments 和函数 "divide:by:" 组成的数组 - 您可以将其替换为等效函数,其中一个参数显式为浮点值:

extension NSExpression 
    var floatifiedForDivisionIfNeeded: NSExpression 
        if function == "divide:by:", let args = arguments, let last = args.last,
          let firstValue = args.first?.constantValue as? NSNumber 
            let newFirst = NSExpression(forConstantValue: firstValue.doubleValue)
            return NSExpression(forFunction: function, arguments: [newFirst, last])
         else 
            return self
        
    

【讨论】:

那么我们应该修改字符串以包含小数点吗?这是唯一的方法吗?【参考方案3】:

我认为您需要用户 DDMathParser 在这种情况下最好。我在我的一个项目中使用过它,该项目面临与您遇到的相同问题

DDMathEvaluator *eval = [DDMathEvaluator defaultMathEvaluator]; id value=[eval evaluateString:@"1/2" withSubstitutions:nil error:&error]; NSLog(@"Result %@",value); Result 0.5

【讨论】:

【参考方案4】:

Rickster 的解决方案有效,但在 5*5/2 这样的表达式上存在问题,其中第一个参数(此处为 5*5)不仅仅是一个数字。

我在这里找到了一个适合我的不同解决方案:https://***.com/a/46554342/6385925

【讨论】:

【参考方案5】:

对于仍然有这个问题的人,我做了一个快速修复:

extension String 
    var mathExpression: String 
        var returnValue = ""
        for value in newString.components(separatedBy: " ") 
            if value.isOperator 
                returnValue += value
             else 
                returnValue += "\(Double(value) ?? 0)"
            
        
        
        return returnValue
    
    
    var isOperator: Bool 
        ["+", "-", "/", "x", "*"].contains(self)
    

【讨论】:

以上是关于NSExpression 1/2的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSExpression 计算小于值?

从 NSExpression 捕获 NSInvalidArgumentException

使用“现在”的 NSExpression 函数

NSExpression 捕获无效参数

使用 NSExpression 时捕获 NSInvalidArgumentException 的正确方法 [重复]

NSExpression 使用 sqrt: 函数导致 NSInvalidArgumentException