我目前正在将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和答案值,例如:
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]]);
最佳答案
您不会失去任何需要担心的精度。这些是正确的值。大约只有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的输出精度可能会降低十进制小数,并且四舍五入到最接近的值,因此答案看起来更好。
关于ios - 值与NSNumber不一致以进行双倍乘法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23854885/