iPhone在'if'语句中产生奇怪的结果

时间:2010-06-14 16:05:40

标签: iphone objective-c

我有一个UIPicker,用户输入指定的时间(即13:00,13:01,13:02等) - 这决定了他们的分数。一旦他们点击按钮,就会通过这个'if-else'语句确定得分。一切似乎都很有效 - 但我得到了一些不稳定的行为。这是代码:

    //Gets my value from the UIPicker and then converts it into a format that can be used in the 'if' statement.    
    NSInteger runRow = [runTimePicker selectedRowInComponent:2];
    NSString *runSelected = [runTimePickerData objectAtIndex:runRow];
    NSString *runSelectedFixed = [runSelected stringByReplacingOccurrencesOfString:@":" withString:@"."];

    //The actual 'if' statment.
    if ([runSelectedFixed floatValue] <= 13.00) {
    runScore = 100;
} else if ([runSelectedFixed floatValue] <= 13.06) {
    runScore = 99;
} else if ([runSelectedFixed floatValue] <= 13.12) {
    runScore = 97;
} else if ([runSelectedFixed floatValue] <= 13.18) {
    runScore = 96;
} else if ([runSelectedFixed floatValue] <= 13.24) {
    runScore = 94;
} else if ([runSelectedFixed floatValue] <= 13.30) {
    runScore = 93;
} else if ([runSelectedFixed floatValue] <= 13.36) {
    runScore = 92;
} else if ([runSelectedFixed floatValue] <= 13.42) {
    runScore = 90;
} else if ([runSelectedFixed floatValue] <= 13.48) {
    runScore = 89;
} else if ([runSelectedFixed floatValue] <= 13.54) {
    runScore = 88;
}

现在,当我测试程序时,当我选择'13:00'为'100'时,我将得到预期的结果。当我选择'13:01和13:05'之间的所有时间时,我也得到'99'的预期结果。但是,当我选择'13:06'时,它会给我一个'97'的分数。我还在'13:07到13:12'得到了'97'的分数 - 这是理想的结果。为什么我会在'13:12'上获得'97',但在'13:06'上没有'99'?这可能是内存泄漏还是什么???

4 个答案:

答案 0 :(得分:4)

不,不是内存泄漏,而是浮点数如何工作的一个基本方面。并非所有有理数都可以通过浮点数准确表示。有些数字比其他数字更准确。记录良好else where

最好将时间分成整数小时和分钟..

NSArray *components = [@"13:42" componentsSeparatedByString:@":"]
int hrs = [[components objectAtIndex:0] intValue];
int mins = [[components objectAtIndex:1] intValue];

答案 1 :(得分:1)

在源代码中输入原始浮点数时,假定它是double。将其与[runSelectedFixed floatValue]进行比较时,float类型为float,编译器必须先将double投射到13.06,然后进行比较。

因为浮点数不能完美地表示所有基数为10的数字,所以您的值在内部四舍五入到最近的浮点表示。例如,当您输入float时,13.058表示实际上可能是double(仅仅是一个理论示例,您实际上具有比此更高的精度)。由于13.059具有更高的精确度,因此当您输入13.06时,它可能会保留float。因此,一旦你比较两者,你将不会总是得到你期望的结果。请务必阅读the Wikipedia article on floating point,以便了解浮点代码的限制和正确使用。

您可以通过在每个文字的末尾添加f,使代码中的所有浮点数都高于} else if ([runSelectedFixed floatValue] <= 13.06f) { 文字。例如:

int runScore = 100 - (int)(([runSelectedFixed floatValue] - 13.0f) / 0.06f);

这将使您的所有数字保持相同的精确度,并有助于避免您在上面看到的问题。但是,您不应该使用100行if-else块来完成可以通过简单等式完成的操作:

{{1}}

添加适合您的代码的边界。还要考虑首先将runSelectedFixed拆分为hrs和minutes组件,如同mustISignUp建议的那样。

答案 2 :(得分:0)

为什么不将它转换为整数? e.g。

NSString *runSelectedFixed = [runSelected stringByReplacingOccurrencesOfString:@":" withString:@""];

...

答案 3 :(得分:0)

你如何将时间(13:06)转换为花车(13.06)? 6/60ths = 0.1,这将导致您看到的结果。我猜这是真正的原因,但一个好的解决方案与@mustISignUp建议的相同。