我有一个值存储为NSDecimalNumber,当我将其转换为double时,它会失去精度。
对于我正在调试的当前数据,值为0.2676655。当我发送一个doubleValue消息时,我得到0.267665。它正在截断而不是舍入,这会破坏一些使用哈希来检测同步操作的数据更改的代码。
NSDecimalNumber实例来自第三方框架,所以我不能用原始double替换它。最终它被插入一个NSMutableString所以我在一个字符串表示后,但它需要通过格式说明符“%。6lf”传递,基本上我需要十进制后的六位数,所以它看起来像0.267666。
如何在不失去精确度的情况下实现这一目标?如果有一种很好的方法来格式化NSDecimalNumber而不转换为可以正常工作的双精度。
答案 0 :(得分:4)
NSDecimalNumber实例来自第三方框架,所以我 不能用原始的双倍替换它。
是的,你可以。 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);
答案 1 :(得分: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]);
如果需要,这具有使用区域设置感知格式化程序的另一个好处。数字格式化程序的结果是所需的字符串。