2012-07-18 136 views
0

我有一个值被存储为一个NSDecimalNumber,当我将它转换为双精度时,它正在失去精度。如何将NSDecimalNumber转换为双倍

对于我正在调试的当前数据段,值为0.2676655。当我发送一个doubleValue消息时,我得到0.267665。它截断而不是四舍五入,这对一些使用哈希来检测数据更改以进行同步操作的代码造成严重破坏。

NSDecimalNumber实例来自第三方框架,所以我不能用原语double来代替它。最终它被插入到一个NSMutableString中,所以我在一个字符串表示后,但它需要通过一个格式说明符“%.6lf”,基本上我需要小数点后六位数字,因此它看起来像0.267666。

我该如何做到这一点而不失精度?如果有一种很好的方式来格式化NSDecimalNumber而不转换为双精度,那也可以。

回答

4

NSDecimalNumber实例来自第三方框架,所以我 不能用一个原始的double来代替它。

是的,你可以。 NSDecimalNumber是NSNumber的,这是一个有点太有帮助的一个不变的子类,当涉及到转换:

double myDub = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithDouble:((double)0.2676655)] doubleValue]]; 

最终它被插入的NSMutableString所以我一个 字符串表示之后,但是它需要通过格式 说明符“%.6lf”,基本上我需要小数点后六位数,所以 看起来像0.267666。

双精度遗憾的是不圆的,而是得到一个字符串值,通过百万分之一的断不是什么大不了的事(我希望)的:

NSDecimalNumber *num = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithDouble:((double)0.2676655)] decimalValue]]; 
NSString *numString = [NSString stringWithFormat:@"%.6lf", [num doubleValue]]; 
NSLog(@"%@",numString); 
2

我认为你是在错误的路径和某处失去了做什么。

首先,请记住,在objective-c lond double中是不支持,因此您最好使用类似%f而不是%lf的内容。 [可在目标c运行时编程指南的“类型编码”下的文档库中找到]

然后我宁可期望值显示为被截断,因为doubleValue返回近似值,但范围你正在使用的是在正确的范围内。

你应该用一个简单的格式,而不是中移动的数字,如:

// first line as an example for your real value 
    NSDecimalNumber *value = [NSDecimalNumber decimalNumberWithString:@"0.2676655"]; 
    NSNumberFormatter *numFmt = [[NSNumberFormatter alloc] init]; 
    [numFmt setMaximumFractionDigits:6]; 
    [numFmt setMinimumFractionDigits:6]; 
    [numFmt setMinimumIntegerDigits:1]; 
    NSLog(@"Formatted number %@",[numFmt stringFromNumber:value]); 

这有如果需要使用的语言环境意识到格式化的另一个好处。数字格式化程序的结果是所需的字符串。