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 捕获 NSInvalidArgumentException