在我的应用程序中,我使用的是使用json进行通信的外部API。今天我在浮动和NSNumber之间遇到了奇怪的事情(可能是由于我在iOS上缺乏经验而感到奇怪)。问题是我在API响应中收到一个浮点数,在这种特殊情况下它是135.99。当本机obj-c json解析器解析响应时,它会使用该值创建NSNumber。它完美无缺。但是当我开始使用这个API时,我不知道原生的json解析器是怎么回事,所以我一直在做这样的事情:
NSNumber * number = [NSNumber numberWithFloat:[[response objectForKey:@"Number"] floatValue]];
所以,上面发生的事情实际上是将NSNumber转换为float并使用该float创建新的NSNumber。有什么奇怪的呢?奇怪(对我来说)是上面的行生成NSNumber值为135.99001而不是135.99这是正确的。
我知道浮点数算法真的搞砸了,尤其是像PHP这样的语言(0.2 + 0.7不等于0.9),但是我没想到像Objective-c这样的语言,这是C语言的超集,我会发现这样的混乱。有没有人对这个问题有一个很好的解释?
答案 0 :(得分:2)
你犯了一个初学者错误,那就是假设“float”是浮点数的正确类型。不是。除非你有充分的理由使用float,否则“double”是你应该使用的类型。 JSON解析器将不可避免地使用[NSNumber numberWithDouble:...]来创建它们存储的NSNumber对象(或[NSNumber numberWithLongLong:...]或NSDecimalNumber),但永远不会 [NSNumber numberWithFloat:]。< / p> 与double相比,
float的精度非常有限。你可以肯定,在大多数情况下,由于精度有限,[NSNumber numberWithFloat:...]会给你不同的结果。
答案 1 :(得分:0)
对于像C这样的语言(我也怀疑是PHP),float(和double)算术并不是真的与语言有关,而是与底层硬件有关。
对于现代计算机而言,这意味着由CPU实现的IEEE浮点运算,因此如果用C,Pascal,FORTRAN等编写程序,就会遇到同样的问题。它们都只是调用CPU的浮点指令和留在那。
答案 2 :(得分:-1)
漂浮物会发生奇怪的事情。它们的本质是它们的一部分。
除此之外,我不完全理解你为什么要将你的好NSNumber转换(不仅仅是类型转换)为浮动只是为了从浮点数中创建一个新的NSNumber对象,你永远不应该期望两个浮点值相等,即使你想不出他们应该有什么不同的任何理由。
这意味着,在比较浮点数时,你永远不应该比较float1 == float2
。更好地比较abs(float1-float2) < 0.001
或重要性。
关于浮动的这些行为的一般性在本网站上得到了很好的解释:http://floating-point-gui.de/