【问题标题】:Convert to Float and Calculate转换为浮点数并计算
【发布时间】:2013-01-04 10:29:38
【问题描述】:

我有一个包含多个数字和运算符的字符串

@"5+4-9/10".

如何从中得到结果?

我想在我正在使用的计算器中使用它。当按下数字或运算符时,我将不得不动态显示结果。

我在 android 中使用了 arity jar 文件。但我无法在 iPhone 中实现类似的功能。

【问题讨论】:

  • 您的解决方案将是here
  • 当您选择数字时,您必须将数字从 nsstring 转换为 int 或根据需要浮动..
  • 对于简单的表达式,你可以使用NSExpression,见e.g. stackoverflow.com/a/12500518/1187415。否则使用适当的数学表达式解析器。
  • @Chandra Sekhar :我更正了我的第二个选项,您可以使用它。
  • @Chandra Sekhar :我认为您必须至少传递一个浮点值。看我的回答。

标签: iphone objective-c ios


【解决方案1】:

这个怎么样-

NSString *formula = @"1+5*6";
NSExpression *exp = [NSExpression expressionWithFormat:formula];
NSNumber *resultForCustomFormula = [exp expressionValueWithObject:nil context:nil];
NSLog(@"%f", [resultForCustomFormula floatValue]);

编辑: 现在我考虑了您的要求并使用NSScanner 制作了一个方法您不会相信在Mr. Borrrden 建议我使用它之前我没有使用NSScanner,我发现它很棒。见下面的方法-

-(NSMutableString *)formatString:(NSString *)formula
{
    // Let's check if there any wrong (.) value exm: 1/.2 or .7+3 
    // 1/0.2 and 0.7+3 are okay but above are incorrect so first fix them

    NSString *str = formula;
    NSInteger c = 0;
    for(int i=0; i<[str length]; i++)
    {

        if([[NSString stringWithFormat:@"%c",[str characterAtIndex:i]] isEqualToString:@"+"] ||
           [[NSString stringWithFormat:@"%c",[str characterAtIndex:i]] isEqualToString:@"-"] ||
           [[NSString stringWithFormat:@"%c",[str characterAtIndex:i]] isEqualToString:@"/"] ||
           [[NSString stringWithFormat:@"%c",[str characterAtIndex:i]] isEqualToString:@"*"])
        {
            if([str length] > i+1)
            {
                if([[NSString stringWithFormat:@"%c",[str characterAtIndex:i+1]] isEqualToString:@"."])
                {
                    formula = [formula stringByReplacingCharactersInRange:NSMakeRange(i+1+c, 1) withString:@"0."];
                    c++;
                }
            }
        }
    }

    // Now we will convert all numbers in float

    NSString *aString;
    float aFloat;
    NSMutableString *formattedString = [[NSMutableString alloc]init];

    NSScanner *theScanner = [NSScanner scannerWithString:formula];
    while ([theScanner isAtEnd] == NO) 
    {

        if([theScanner scanFloat:&aFloat])
        {
            [formattedString appendString:[NSString stringWithFormat:@"%f",aFloat]];
        }

        if([theScanner scanUpToCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&aString])
        {
            [formattedString appendString:aString];
        }
    }
    return formattedString;
}

这会将 (2.222/.4)+9999-7+0.7*.13 转换为 (2.222000/0.400000)+9999.000000-7.000000+0.700000*0.130000 .
在使用NSExpression之前调用这个方法。

NSString *formula = @"(2.222/.4)+9999-7+0.7*.13";
NSString *formattedString = [self formatString:formula];
NSExpression *exp = [NSExpression expressionWithFormat:formattedString];
NSNumber *resultForCustomFormula = [exp expressionValueWithObject:nil context:nil];
NSLog(@"Result = %f", [resultForCustomFormula floatValue]);

//OutPut: Result = 9997.646484

注意:我并不是说它适用于所有公式字符串。可能在某些情况下它不起作用。但它适用于一般方程。

【讨论】:

  • 我得到了底价。我尝试了 7/4 并返回 1.0000
  • 所以亲爱的,它与表达式验证无关,您必须自己完成所有关于逻辑的事情:)
  • 这种方法的问题是你试图解析一个字符串,就像另一个解析器 (NSExpression) 一样。解析很困难,模仿另一个解析器的尝试通常会失败,至少对于许多输入情况而言)。一个例子:@"1/.2"。即使你解决了这个问题,我相信还有其他人。所以问题是你选择的一般方法。这就是我投反对票的原因。
  • 主要问题没有被触及(甚至恶化)。您添加了代码来修复代码失败的一种特殊情况。我仍然可以看到许多其他不起作用的情况。然而,正如我所描述的,我认为这是一个糟糕的解决方案的原因是试图模仿一个重要的解析器的一般方法。
  • @TheTiger 我不同意它比其他人更好。这种包含无数隐藏错误的代码是导致项目长期失败的原因。我已经看到项目因为调试成本激增而失败。问题的根源在于程序员,他们表面上快速实现功能,但从不花时间理解他们的代码的含义。
【解决方案2】:

Note that : 你必须至少传递一个浮点值

我知道这不是最好的方法,但是这样的东西可以为你工作。

NSString *formula = @"5+4-9/10";
NSString *str = [formula lastPathComponent];
formula = [formula stringByReplacingOccurrencesOfString:str withString:[NSString stringWithFormat:@"%@.0",str]];
NSString *strCal=[NSString stringWithString:formula];
NSExpression *exp=[NSExpression expressionWithFormat:strCal];
float result=[[exp expressionValueWithObject:nil context:nil] floatValue];
NSLog(@"result:%f",result);

您可以使用GCMathParserDDMathParser

不知道这是否是最有效的方法,但还是写来帮助你......!!!

【讨论】:

  • 你不需要假人NSPredicate,参见例如stackoverflow.com/a/12500518/1187415.
  • 我收到警告“NSPredicate 可能无法响应 leftExpression”
  • @BhavinChitroda:您的第二个示例不正确。它会导致编译器警告,并且 NSLog 输出为“floor:((19 - 10) / 2)”。
  • @BhavinChitroda 你能告诉我如何得到确切的值而不是底值
【解决方案3】:

您可以将“所有”数字解析为浮点数:

NSMutableString *numericExpression = [NSMutableString stringWithString:@"4+3/2-7/4"];

NSMutableString *nExp=[NSMutableString stringWithString:@""];
BOOL innum=false;
BOOL dotfound=false;

for (NSInteger charIdx=0; charIdx<numericExpression.length; charIdx++){
        NSString *substr=[NSString stringWithFormat:@"%C",[numericExpression characterAtIndex:charIdx]];
        if (isdigit([numericExpression characterAtIndex:charIdx])) {
            // in number
            innum=true;
        }else if ([substr isEqualToString:@"."]){
            // dot found ...
            innum=true;
            dotfound=true;
        }else{
            // not in number
            if (innum && dotfound) {
                NSLog(@"all good (*).*");
            }else if(innum && !dotfound){
                NSLog(@"adding .0");
                [nExp appendString:@".0"];
            }
            innum=false;
            dotfound=false;
        }
    [nExp appendString:substr];
    NSLog(@"%@",nExp);
}

NSExpression *expression = [NSExpression expressionWithFormat:nExp];
NSNumber *result = [expression expressionValueWithObject:nil context:nil];
 NSLog(@"calc %@ = %@",nExp,result);

【讨论】:

    猜你喜欢
    • 2017-08-29
    • 2013-07-16
    • 2013-01-21
    • 2019-11-21
    • 1970-01-01
    • 2013-06-19
    • 2014-04-28
    • 1970-01-01
    • 2021-08-11
    相关资源
    最近更新 更多