4

在我的应用程序中,我使用了一个使用 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 语言的超集,我会发现这样乱来。有人对这个问题有很好的解释吗?

4

3 回答 3

2

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

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

于 2014-05-11T21:24:24.520 回答
0

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

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

于 2013-02-14T09:46:39.003 回答
-1

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

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

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

于 2013-02-14T09:41:36.640 回答