0

我有一个值存储为 NSDecimalNumber,当我将其转换为双精度时,它会丢失精度。

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

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

我怎样才能在不丢失精度的情况下做到这一点?如果有一种很好的方法来格式化 NSDecimalNumber 而无需转换为双精度也可以。

4

2 回答 2

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);
于 2012-07-18T19:26:46.410 回答
2

我认为您走错了路,不知所措。

首先,请记住,objective-c 中不支持lond double ,因此您最好使用 %f 之类的东西而不是 %lf。[可在 Objective 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]);

如果需要,这还有一个好处是使用区域感知格式化程序。数字格式化程序的结果是所需的字符串。

于 2012-07-18T20:52:22.183 回答