【问题标题】:NSDecimalNumber returning wrong uint64_t valueNSDecimalNumber 返回错误的 uint64_t 值
【发布时间】:2016-05-31 04:51:09
【问题描述】:

我的应用程序通过persistentId 记住MPMediaItems,就像一个人一样。它将 persistentId 保存在 JSON 文件中,稍后读取和解析该文件。 NSJSONSerialization 创建一个 NSDecimalNumber 来包含 Id,我的应用稍后在 MPMediaQuery 中使用它来获取 MPMediaItem。

我发现有时会发现错误的 MPMediaItem。当我再四处寻找时,我发现当我将 NSDecimalNumber 转换为 uint64_t 值时,[NSNumber unsignedLongLongValue] 返回了错误的值!

NSDecimalNumber* const songId = _songId;
uint64_t         const songIdValue = songId.unsignedLongLongValue;

songId is      1457249251113381177
songIdValue is 1457249251113381120
-or-
songId is      0x1439307919d12d39
songIdValue is 0x1439307919d12d00

什么鬼?看起来低字节在将此 NSDecimalNumber 转换为 uint64_t 时被清除。这是 NSDecimalNumber 的某种正确行为吗?我发现其中有错误吗?

我正在通过将 NSDecimalNumber 从 NSJSONSerialization 转换为字符串并使用 [NSString longLongValue] 将字符串转换为 uint64_t 来解决此问题。

这很可怕,因为我现在似乎必须检查我在 JSON 文件中存储大整数的每个地方,并确保我以这种 NSString-y 方式评估它们。

【问题讨论】:

  • 我在这里找到了一条评论,说 NSDecimalNumber 在转换为 uint64_t 之前先转换为双精度数。因此,任何超过 53 的有效位都会被清除,正如我在这里看到的那样。令人难以置信的是,Apple 让这一切站稳了脚跟! NSJsonSerialization 在为整数而不是 NSNumber 选择此类时出错。我打算将我的 JSON 解析切换到 JSONKit,我建议其他人也这样做。

标签: ios cocoa nsdecimalnumber


【解决方案1】:

如果你想保持最大的精度,你可以:

仅适用于 NSDecimalNumbers,

当您将 NSDecimalNumber 的值传输到另一个不是 NSDecimalNumber 的变量时,请使用 NSString。 [NSDecimalNumber longLongValue] 或 [NSDecimalNumber doubleValue] 等方法不够具体。

NSDecimalNumber     *songId;
uint64_t            songIdValue;
NSString            *intermediateStr;

songId = [NSDecimalNumber decimalNumberWithString:@"1457249251113381177"];  
intermediateStr = songId.stringValue;
songIdValue = intermediateStr.longLongValue;

为什么使用字符串比其他方法更精确?我不知道。但是 songIdValue 包含正确的值,没有任何损失。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 2019-02-03
    • 2014-01-16
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多