2016-03-25 4 views
1

В одном из моих апи я получаю ниже форму ответа сервера (Если преобразовать данные в строку)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]; 

Its вернуться

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

}

Из-за нескольких мест после десятичного в целом поле его создавая проблему в расчете.

Я думаю, что метод сериализации JSON преобразование его внутри, но не знаю, как решить эту

+0

Какой ты прохождения для чтения вариант? –

+0

его 0 по умолчанию –

+0

sometime float недостаточно точен при значениях типа. это не повредит вашей программе, пока вам не понадобится точное значение. когда вы обходите вещи, вы получите то, что хотите здесь. –

ответ

0

Вы используете арифметики с плавающей точкой. То, что вы видите, абсолютно нормально. У вас будет то же самое, если вы только назначили 68.6.

Как вы это решаете? Изучая арифметику с плавающей точкой. Но какие проблемы вы действительно видите? Вы просто паникуете, потому что видите множество девяток или есть настоящая проблема?

Что заставляет вас думать, что преобразование данных обратно в JSON приведет к тому, что сервер неправильно понял? Ты это пробовал? Вы беспокоитесь о теоретической возможности, или у вас есть фактическое доказательство проблемы? Очевидно, сервер хранит что-то округленное до одного десятичного знака.

Я имею в виду, серьезно ли вы понимаете, что вы беспокоитесь о выходе инструкции NSLog?

+1

Проблема заключается в ее преобразовании .6 в .599999999, который получает сбой при отправке значения обратно на сервер, потому что теперь значение, которое у меня есть, равно 59999 of .6 –

+0

@iOSRocks В этом случае проблема на вашем сервере. Есть способы исправить это, например. используя 'NSDecimalNumber' для хранения чисел, с настраиваемым парсером и кодировщиком JSON, но гораздо проще исправить сервер. – Sulthan

+0

То же самое отлично работает с Android, поэтому мы не можем изменить код на стороне сервера –

5

@gnasher намекнул на проблему, но не объяснил это подробно.

Компьютеры используют двоичную плавающую точку для представления чисел с плавающей запятой внутри.

Число с плавающей запятой обычно хранится как поплавок, так и двойной. На большинстве 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); 

Displays:

aFloat (1 decimal place)= 68.6 

Строка JSON, которую вы обрабатываете, содержит в ней номера, которые не входят в кавычки. Когда вы конвертируете строку JSON в объект Cocoa, значение «Total» сохраняется как объект NSNumber, возможно, используя внутренний тип double.

Если вам нужно выполнить математику по своему «итоговому» значению, вам нужно, чтобы это число.

Если вы хотите избежать ошибок преобразования десятичного кода, измените код сервера, чтобы отправить значение «Всего» в виде строки (в кавычках), а не числовое значение. Тогда функция 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, чтобы добавить параметр, который будет создавать объекты NSDecimalNumber для десятичных значений, содержащихся в строке JSON.Вы опубликовали свой собственный парсер 'JSON'? –

+0

Вверх Голосуйте за качественный ответ и хорошее объяснение. – user3182143

1

Это помогло устранить проблему

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

Вывод этого журнала 68,6

+0

Почему это работает? лол. – neobie

Смежные вопросы