与NSNumber不一致的值,以乘以倍增

时间:2014-05-25 11:42:23

标签: ios objective-c nsnumber nsnumberformatter

我目前正在将NSString值解析为NSNumbers,然后将它们添加到名为" data"的对象中的NSMutableArray调用操作数中。像这样:

NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:*operandString];
[data.operands addObject:myNumber];

然后我检索这些数字,对它们执行一些数学运算,然后更新数组:

double x = [[data.operands objectAtIndex: i]doubleValue];
double y = [[data.operands objectAtIndex: i + 1]doubleValue];
double answer = x * y;
[data.operands replaceObjectAtIndex:(i) withObject:[NSNumber numberWithDouble:answer]];

当我得到答案时,一切看起来都很好,例如:(3.33 * 5 = 16.65)

但是,当我查看调试器时,我看到了x和答案的一些疯狂值,例如:

x = 3.3300000000000001
答案= 16.649999999999999

为什么会这样?解析这些后面和第四个,我是否会失去一些精确度?我是如何使用NSNumberFormatter来解析字符串的?

我遇到麻烦的原因是因为我试图确保没有双重溢出错误,所以我使用这个简单的测试来检查完整性:

    if (answer / y != x){
        //THROW OVERFLOW ERROR
    }

有了上述疯狂的数字,这总是不一致的。当我NSLog得到答案时,它很好:

NSLog (@"%g", [[data.operands objectAtIndex:i]doubleValue]]);

相同
NSLog (@"%f", [[data.operands objectAtIndex:i]doubleValue]]);

1 个答案:

答案 0 :(得分:2)

您不会失去任何需要担心的精确度。这些是正确的价值观。只有大约2 ^ 60个不同的双数,有限集必须试图大致覆盖双倍覆盖范围内的无限“数量”。

换句话说,在计算机领域和你的

中没有确切的答案
   if (answer / y != x){
       //THROW OVERFLOW ERROR
   }

不行。或者它可能在很多时候都可以工作,但是如果你推动它就会失败。相反,你需要承认双精度的有限精度(相当高的精度):

  //Don't waste time worrying like this...
  if (fabs(answer / y - x) > 1e-12*fabs(answer)){
       //Not correct or useful thing to check don't use this - i did not check 
   }


   // let the math package handle it:
   if (isnan(answer)){
     // we gots problems
   }

   if (!isnormal(answer)){
     // we gots some other problems
   }

另外不要忘记10 ^ 300是一个非常大的数字,双打工作相当不错。要使用32位浮点数,您需要更加注意执行顺序等。

NSLog很可能以较少的精度小数输出,并且舍入到最接近的位置,因此答案看起来更好。