之前在學習C語言的時候課堂上,老師就強調(diào),不能使用float類型的數(shù)字進行相等比較判斷。這個也確實聽進去了,也明白原因是float是存儲是不精確的。但是真正開發(fā)實踐的時候,或許只有出問題了,才會醒悟:哦,原來是這樣。這個問題在高大上的OC上同樣存在,稍不注意就會出現(xiàn)問題。
iOS開發(fā)中,接受后臺的響應,然后轉化為模型對象,最終轉化為NSString對象,然后控件顯示出來。這一切都是那么的自然那么的熟悉。
一個數(shù)字,可以定義為number類型,也可以定義為字符串問題。如果后臺返回的是字符串類型。在iOS json序列化的時候,會把字符串類型轉化為NSString對象,這個一點問題沒有。但是如果后臺返回的是number類型。json序列化會將number類型轉化為NSNumber對象。使用的時候,想當然的會將NSNumber轉化為NSString對象。這樣做很自然啊,沒有問題,也用一兩個數(shù)字測試了,轉化是精確的。測試那邊也測試通過了,然后產(chǎn)品上線了。最終,還是出現(xiàn)了問題。不說大數(shù),就10以內(nèi)的吧。有這么多的轉換不精確。(如下圖)不信你可以試一下,讓后臺定義double類型數(shù)據(jù)66.6,你轉化為字符串會發(fā)現(xiàn)就是66.59999999999999。測試發(fā)現(xiàn)double轉化為NSNumber的時候就會出現(xiàn)問題。double表示的字面值和其存儲的值一般是不一樣的,轉化為NSNumber之后,有很大一些數(shù)字,在NSNumber的stringValue上會出錯。
NSString* json = @"{\"number\":66.6}";
NSData* data = [json dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary* dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
id object = dic[@"number"];
NSLog(@"%@",[object class]);
NSLog(@"%@",object);
打印結果
__NSCFNumber
66.59999999999999

解決方法可以是把取String的doubleValue,然后再.2f保留兩位小數(shù)進行構造字符串。千萬不能取floatValue,floatValue在大于15萬的浮點數(shù)字就會出現(xiàn)不精確了(筆者做過遍歷測試)。而doubleValue在數(shù)十億的范圍內(nèi)都是字面上精確的。
根本解決方法還是勸后臺的同事把請求返回的數(shù)據(jù)全部設置為String類型
如果涉及到計算的問題,那就只得乖乖轉化為NSDecimalNumber對象了。