我使用NSNumber存储各种值,但有时在对值进行计算和为结果初始化新的NSNumber对象时会遇到问题。我已经想出了如何克服它的方法,但在我的一生中,我无法解释它的工作原理,而且由于我对计算机环境中的数值(双、浮子等)的掌握很弱,所以我想问这个问题来学习。:-)
第一个例子是,当我在不同的测量单位之间转换时,在这个特殊的情况下,它是在mmol/L和mg/dl之间。得到一个表示NSNumber /L值的值,提取它的双值并进行计算。然后用NSNumber创建一个新的-initWithDouble并返回结果。
然而,我会有奇怪的怪癖。当mmol/L值为10.0时,相应的mg/dl值为180.0 (很明显,仅为18)。但是,当我以后需要让用户在选择器视图中选择一个新值并使用NSNumber -intValue获取当前值的整数位(使用我自己的扩展来获取小数)时,int值是179!在计算过程中,我检查了所有中间的双值,以及新的NSNumber的双值,结果都很好(结果是180.00000)。有趣的是,并不是所有的值都会出现这种情况,只有一些值(10.0是一个真正的例子)。
第二个例子是当我从Sqlite3数据库检索双值并将它们存储在NSNumbers中时。再说一遍,大多数价值观都很好,但偶尔我会得到一些奇怪的东西。例如,如果我将6.7分保存在数据库中(检查何时保存,即实际上值),则检索后的NSNumber将显示为6.699999。(我在写文章的时候已经记不起来了,如果数据库也是这样的话,但我想是的--我可以稍后再查。)
可以通过使用中间浮点数和NSNumber initWithFloat而不是initWithDouble来绕过这两个实例。因此,例如,在我的转换中,我只需执行一个float resultAsFloat = resultAsDouble,并为新的NSNumber使用initWithFloat。
对于这个冗长的问题表示歉意,如果这仅仅是我自己对处理数值的知识所缺乏的,但如果有人能向我解释这一点,我会非常感激的!
谢谢,
安德斯
*编辑1 *
单元转换示例的代码:
-(NSNumber *)convertNumber:(NSNumber *)aNumber withUnit:(FCUnit *)aUnit {
// if origin unit and target unit are the same, return original number
if ([aUnit.uid isEqualToString:self.target.uid])
return aNumber;
// determine if origin unit and target unit are comparable
if (aUnit.quantity != self.target.quantity)
return nil;
// if so, convert the number...
// get bases
double originBase;
double targetBase;
if (aUnit.metre != nil) {
originBase = [aUnit.metre doubleValue];
targetBase = [self.target.metre doubleValue];
} else if (aUnit.kilogram != nil) {
originBase = [aUnit.kilogram doubleValue];
targetBase = [self.target.kilogram doubleValue];
} else if (aUnit.second != nil) {
originBase = [aUnit.second doubleValue];
targetBase = [self.target.second doubleValue];
} else if (aUnit.quantity == FCUnitQuantityGlucose) {
// special case for glucose
if ([aUnit.uid isEqualToString:FCKeyUIDGlucoseMillimolesPerLitre]) { // mmol/L -> mg/dl
originBase = 1;
targetBase = 0.0555555555555556; // since 1 / 0.0555555555555556 = 18
} else if ([aUnit.uid isEqualToString:FCKeyUIDGlucoseMilligramsPerDecilitre]) { // mg/dl -> mmol/L
originBase = 0.0555555555555556;
targetBase = 1;
}
}
// find conversion rate
double rate = originBase / targetBase;
// convert the value
double convert = [aNumber doubleValue] * rate;
// TMP FIX: this fixes an issue where the intValue of convertedNumber would be one less
// than it should be if the number was created with a double instead of a float. I have
// no clue as to why...
float convertAsFloat = convert;
// create new number object and return it
NSNumber *convertedNumber = [[NSNumber alloc] initWithFloat:convertAsFloat];
[convertedNumber autorelease];
return convertedNumber;
}发布于 2010-09-16 16:10:18
尝试使用NSDecimalNumber。这里有一个很好的教程:
http://www.cimgf.com/2008/04/23/cocoa-tutorial-dont-be-lazy-with-nsdecimalnumber-like-me/
发布于 2010-11-05 16:38:07
如果我没有错,如果我记得大学里合适的课程,我认为这是一个从现实(在那里你有无限的价值)到虚拟(在那里你有有限的值,即使你有很多)的问题:所以你实际上不能代表所有的数字。你还必须面对你正在做的操作:乘法和除法会产生很多这样的麻烦,因为你会有很多十进制数,在我看来,基于C的语言并不是最好的处理这类问题的语言。希望这将为您提供更好的信息来源:)。
https://stackoverflow.com/questions/3728213
复制相似问题