【问题标题】:Inconsistent values with NSNumber to double multiplication与 NSNumber 不一致的值进行双倍乘法
【发布时间】:2014-05-25 11:42:22
【问题描述】:

我目前正在将 NSString 值解析为 NSNumbers,然后将它们添加到一个名为“数据”的对象中的称为操作数的 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 和 answer 的一些疯狂值,例如:

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]]);

【问题讨论】:

    标签: ios objective-c nsnumber nsnumberformatter


    【解决方案1】:

    您不会丢失任何需要担心的精度。这些是正确的值。只有大约 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 可能输出的小数精度较低,并且会四舍五入到最接近的值,因此答案看起来更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      相关资源
      最近更新 更多