2

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

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 记录它,它显示为点。仅供参考

4

5 回答 5

3

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

1.0/2
1.0/2.0
1/2.0

都会工作

于 2013-01-15T20:24:21.230 回答
2

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

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


“分解”位的后续编辑:您知道具有高阶结构的内容中的字符串修改通常是有问题的。有了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
        }
    }
}
于 2013-01-15T20:30:02.957 回答
1

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

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

于 2014-05-19T05:15:57.307 回答
0

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

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)
    }
}
于 2021-10-05T07:41:14.140 回答
0

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

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

于 2021-07-07T06:52:29.867 回答