【问题标题】:NSNumber and float - type casting oddityNSNumber 和 float - 类型转换异常
【发布时间】:2013-01-30 00:59:39
【问题描述】:

在我的应用程序中,我使用了一个使用 json 进行通信的外部 API。今天我遇到了浮点数和 NSNumbers 之间的奇怪行为(可能只是因为我对 iOS 缺乏经验而感到奇怪)。问题是我在 API 响应中收到一个浮点数,在这种特殊情况下它是 135.99。当本机 obj-c json 解析器解析响应时,它会使用该值创建 NSNumber。它工作完美。但是当我开始使用这个 API 的时候,我并不知道原生 json 解析器是怎么做的,所以我一直在做这样的事情:

NSNumber * number = [NSNumber numberWithFloat:[[response objectForKey:@"Number"] floatValue]];

所以,上面发生的实际上是将 NSNumber 转换为浮点数并使用该浮点数创建新的 NSNumber。它有什么奇怪的?奇怪(对我来说)是上面的行生成 NSNumber 的值...... 135.99001 而不是 135.99 这是正确的。

我知道浮点运算真的很糟糕,尤其是在 PHP 之类的语言中(0.2 + 0.7 不等于 0.9),但我没想到在 Objective-c 这样的语言中,它是 C 语言的超集,我会发现这样的乱七八糟的。有人对这个问题有很好的解释吗?

【问题讨论】:

  • 那么,上面发生的事情实际上是将 NSNumber 转换为浮点数并使用该浮点数创建新的 NSNumber。 为什么?
  • 如果您通过完全避免转换来“修复”代码会发生什么:NSNumber * number = [response objectForKey:@"Number"]?
  • 它工作正常,但我犯了上面提到的错误,我已经弄清楚了。我的问题是为什么有两个不同的值(135.99 和 135.99001),而这两种情况下应该有一个相同的值(135.99),而不是如何解决它,因为我已经知道了。
  • 好的,如果您使用double 而不是floatnumberWithDoubledoubleValue)会发生什么?
  • 一般来说,浮点运算并不是真的搞砸了。关于 SO 的证据是,许多人对 f-p 算术的性质、微妙之处和陷阱的理解真的搞砸了

标签: objective-c casting floating-point nsnumber


【解决方案1】:

你犯了一个初学者的错误,那就是假设“float”是浮点数的正确类型。它不是。除非您有充分的理由使用 float,否则“double”是您应该使用的类型。 JSON 解析器将不可避免地使用 [NSNumber numberWithDouble:...] 来创建它们存储的 NSNumber 对象(或 [NSNumber numberWithLongLong:...] 或 NSDecimalNumber),但从不 [NSNumber numberWithFloat:]。

与 double 相比,float 的精度非常有限。您可以确定,在大多数情况下, [NSNumber numberWithFloat:...] 由于精度有限,会给您不同的结果。

【讨论】:

    【解决方案2】:

    对于像 C 这样的语言(我也怀疑 PHP),浮点(和双精度)算术并不真正与语言相关,而是与底层硬件相关。

    对于现代计算机,这意味着由 CPU 实现的 IEEE 浮点运算,所以如果你用 C、Pascal、FORTRAN 等语言编写程序,你会遇到同样的问题。它们都只是调用 CPU 的浮点指令和就这样吧。

    【讨论】:

      【解决方案3】:

      花车会发生奇怪的事情。它们不精确是它们本性的一部分。

      除了我不完全理解你为什么将你漂亮的 NSNumber 转换(不仅仅是类型转换)为 float 只是为了从 float 中创建一个新的 NSNumber 对象之外,你永远不应该期望两个 float 值相等,即使你想不出任何理由为什么它们应该不同。 这意味着,在比较浮点数时,您永远不应该比较 float1 == float2。更好地比较abs(float1-float2) < 0.001 或重要的意义。

      关于浮动的这些行为的一些一般性在这个网站上得到了很好的解释:http://floating-point-gui.de/

      【讨论】:

      • 我在之前的 cmets 中说过这是错误的,因为我不知道 json 解析器会为我创建 NSNumber。我不再那样做了。我只是好奇为什么转换后值会发生变化。谢谢你的回答,我去网站看看。
      • 我认为这个网站很好地解释了这个问题,并提供了很好的指导如何处理这个问题。这个问题对于 CPU 中的数据类型浮点和浮点运算更为普遍。它完全不限于 Objective-C 或 ARM 处理器。
      猜你喜欢
      • 2017-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 2021-02-02
      相关资源
      最近更新 更多