2

文字列を計算したいのですが、これは次のように実行しています。

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

問題は、calculationstringが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」の場合、式には2つの配列とarguments関数"divide:by:"があります。引数の1つが明示的に浮動小数点値である同等の関数に置き換えることができます。

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

この状況に最適なDDMathParserを使用する必要があると思います。私はあなたが直面しているのと同じ問題に直面している私のプロジェクトの1つでそれを使用しました

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

Ricksterのソリューションは機能しましたが5*5/2、最初の引数(ここ5*5)が単なる数値ではない、のような式に問題がありました。

私はここで私のために働く別の解決策を見つけました:https ://stackoverflow.com/a/46554342/6385925

于 2021-07-07T06:52:29.867 に答える
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 に答える