2016-03-25 71 views
1

在我的API我得到以下回復表格服務器之一(如果將數據轉換成字符串)JSONObjectWithData錯了位小數在解析

{"success":true,"order_id":102232,"Total":68.6,"delivery_time":"7:30PM-10:00PM","delivery_date":"2016-03-25"} 

但是,當我用同樣的用

[NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError]; 

其返回

{ 
Total = "68.59999999999999"; 
"delivery_date" = "2016-03-25"; 
"delivery_time" = "7:30PM-10:00PM"; 
"order_id" = 102232; 
success = 1; 

}

由於總場中小數點後的多個地方造成了計算中的創建問題。

我覺得JSON序列化方法,把它的內部,但不知道如何解決這個

+0

哪一個是你通過閱讀選項? –

+0

其默認值爲0 –

+0

某些時候float類型的值不夠精確。它不會傷害你的程序,直到你需要確切的價值。當你回合時,你會在這裏得到你想要的。 –

回答

0

您使用浮點運算。你所看到的是絕對正常的。如果你剛剛分配了68.6,你將會發生完全相同的事情。

你如何解決這個問題?通過學習浮點運算。但是你真正看到了什麼問題?你是否因爲看到大量的九點而感到恐慌,或者是否存在實際問題?

是什麼讓你真的認爲將數據轉換回JSON會產生服務器誤解的東西?你試過了嗎?你是否擔心理論上的可能性,還是你有實際的問題證據?很顯然,服務器存儲的東西四捨五入到一位小數。

我的意思是認真的,你知道你擔心的是NSLog語句的輸出嗎?

+1

問題是它將.6轉換爲.599999999,當我將值發送回服務器時失敗,因爲現在我的值是.59999,而不是.0 –

+0

@iOSRocks在這種情況下,問題出在您的服務器上。有很多方法可以解決這個問題,例如使用'NSDecimalNumber'來存儲數字,使用自定義的JSON解析器和編碼器,但修復服務器要容易得多。 – Sulthan

+0

同樣的事情與Android工作正常,所以我們不能改變服務器端代碼 –

5

@gnasher暗示了這個問題,但沒有詳細解釋它。

計算機使用二進制浮點來表示內部的浮點數。

浮點數通常以float或double的形式存儲。在大多數64位平臺上,float以4字節存儲,double以8字節存儲。

二進制浮點不能精確地表示許多十進制值。在內部,68.6以二進制表示爲一個十進制值爲68.59999999999999的值。這是計算機以浮點形式保存價值時最接近68.6的值。

浮點數和浮點數等二進制浮點值沒有「小數位數」。該值被轉換爲十進制以顯示,或轉換爲字符串,並且存在總是該轉換中發生舍入錯誤的可能性。

採取此代碼爲例如:

float aFloat = 68.6; 
NSLog(@"aFloat = %f", aFloat); 

顯示:

aFloat = 68.599998 

但是,此代碼:

NSLog(@"aFloat (1 decimal place)= %.1f", aFloat); 

顯示器:

aFloat (1 decimal place)= 68.6 

您正在解析的JSON字符串中有不包含引號的數字。將JSON字符串轉換爲Cocoa對象時,「Total」的值會保存爲NSNumber對象,可能在內部使用雙重類型。

如果您需要對「總計」值進行數學計算,那麼您需要將其作爲數字。

如果您希望避免十進制轉換錯誤,請更改您的服務器代碼以將值「Total」作爲字符串(用引號引起來)而不是數字值。然後JSONObjectWithData功能將保持它作爲一個字符串,"68.6"

在這種情況下,你的JSON字符串應該是這樣的:

{"success":true,"order_id":102232,"Total":"68.6","delivery_time":"7:30PM-10:00PM","delivery_date":"2016-03-25"} 

你說:「由於總場的創建問題小數點後的多個地方計算「。什麼問題?在iOS端還是服務器端?

+0

它實際上是iOS上的一個大問題,即JSON解析器將所有數字轉換爲「NSNumber」(雙精度),即使是我們想保留的作爲'NSDecimalNumber'。替代解析器(例如'SBJson')具有相同的問題。有一次,我想解析正確的,我不得不分析解析器,並修復行爲。 – Sulthan

+0

Apple的聲音需要增強NSJSONSerialization以添加一個選項,該選項將爲包含在JSON字符串中的十進制值創建NSDecimalNumber對象。你發佈了你的自定義'JSON'分析器嗎? –

+0

向上投票您的高質量答案和很好的解釋。 – user3182143

1

這解決了我的問題,該日誌的

NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init]; 
[fmt setPositiveFormat:@"0.##"]; 
NSLog(@"%@", [fmt stringFromNumber:dataDict[@"Total"]]); 

輸出爲68.6

+0

這是爲什麼工作?大聲笑。 – neobie