Как мне хранить процентные значения в Базовых данных, которые считываются с UISliders? - PullRequest
4 голосов
/ 23 декабря 2010

Ползунки - это основной элемент взаимодействия пользователя с моим приложением (см. Рисунок ...). Я использую их для записи процентных значений, которые затем сохраняются как Reading s в моем хранилище базовых данных. Исходя из характера процентных значений, я бы сохранял их в виде десятичных значений от 0 до 1, а ползунки устанавливали диапазон от 0 до 1 и непрерывно запускал их действия, изменяющие значения. Когда мне нужно отобразить их, я извлекаю их из хранилища данных и отображаю их в виде типичных процентных значений, например, 67%.

Теперь вот в чем загвоздка: свойство value типа UISlider имеет тип float. Это означает, что я столкнусь с ошибками округления с самого начала. Мне не по вкусу точность, поэтому я надеюсь максимально снизить допустимый предел ошибок при работе с ними во всем приложении.

Какие есть варианты для управления процентными значениями, которые я считываю со своих слайдеров, сохраняю в Базовых данных и отображаю в остальной части моего приложения? Или, что еще лучше, какой из этих вариантов, которые я предложил, подойдет для моего приложения с точки зрения поддерживаемости кода , использования / производительности памяти и точности полученные значения ?

  1. Использовать необработанные числа с плавающей запятой или двойные числа

    На самом деле это ПЛОХО , очевидно из-за ошибок округления. Даже 0,64 превращается в 0,63 в какой-то момент времени (я проверил с моими ползунками, и они достигают много ). С разницей в 0,01 мое приложение определенно не переносит этого. Почему я даже пишу это как вариант?

  2. Установите диапазон ползунка от 0 до 100, прочитайте их, округлите вверх / вниз и сохраните как целые числа

    Это интересный выбор, поскольку я буду отображать только значения как ##%, а не 0.##. Мне не нужно выполнять арифметику с этими значениями, так что все выглядит хорошо:

    // Recording and storing
    // Slider range is 0 to 100
    int percentage = (int) floor(slider.value);             // Or ceil()
    [reading setValue:[NSNumber numberWithInt:percentage]]; // Value is an integer
    
    // Displaying
    NSNumber *val = reading.value;
    [readingLabel setText:[NSString stringWithFormat:@"%d%%", [val intValue]]];
    

    Это не приведет к полному устранению ошибок округления, когда я впервые прочитаю их с моих ползунков (они все еще float s!), Но, думаю, floor() или ceil() должны их сократить. Я не совсем уверен, хотя; может быть, кто-то здесь может дать более глубокое понимание, и именно поэтому я задаю этот вопрос.

  3. Преобразовать и сохранить как NSDecimalNumber объекты

    Я взглянул на класс NSDecimalNumber - проценты - это, в конце концов, факторы base-10 - но, учитывая, что он производит неизменяемые объекты, я не слишком уверен, что мне нравится идея писать длинные вызовы методов повсюду мой код многократно и создает повсеместно автоматически выпущенные объекты.

    Даже создание NSDecimalNumber из примитивов - это боль. В настоящее время я могу думать только об этом:

    // Recording and storing
    // Slider range is 0 to 1
    NSDecimalNumber *decimalValue = [NSDecimalNumber decimalNumberWithString:
                                    [NSString stringWithFormat:@"%0.2f", 
                                        slider.value]];
    [reading setValue:decimalValue]; // Value is a decimal number
    

    Умножение их на 100, поскольку я отображаю их как ##% (как я уже говорил выше), также становится действительно утомительным и создает ненужные дополнительные объекты, которые затем преобразуются в NSString s. Я бы продолжил, но я бы, вероятно, превратил этот пост в напыщенную речь, что определенно не то, ради чего я иду.

    С учетом вышесказанного семантически NSDecimalNumber должно иметь наибольшее значение, потому что, как я уже говорил выше, я считаю, что проценты должны храниться в виде десятичных значений от 0 до 1. Однако, глядя на то, как мое приложение работает с процентными значениями Я не знаю, выбрать ли умножить их на 100 и сохранить как целые числа или работать с NSDecimalNumber.

Вы, наверное, видите, что я уже немного склоняюсь ко второму варианту (x100, используйте целые числа), потому что он просто удобнее и выглядит немного лучше для производительности. Тем не менее, я хотел бы узнать, считает ли кто-то третий вариант лучшим (более перспективным?).

Кстати, я не против изменить свою модель данных, чтобы изменить тип данных атрибута value в моей сущности Reading, и изменить существующий код, чтобы учесть изменения. Я пока не сделал слишком много, потому что остальное время проводил, волнуясь об этом.

Как вы думаете, на какой из вышеперечисленных вариантов я должен пойти?

1 Ответ

5 голосов
/ 23 декабря 2010

Если все, что вам нужно сделать, это прочитать с ползунка, сохранить значения и представить их, то я бы порекомендовал использовать примитивные целые числа, полученные из масштабированного округленного ввода с ползунком с плавающей запятой. В любом случае, ползунок не совсем точный метод ввода, поэтому ваши пользователи не заметят, что округление точно не соответствует расположению пикселя головки ползунка.

Я бы использовал те же рассуждения, что и вы, при определении количества значащих цифр в расчете, в котором в качестве входных данных используются реальные данные (например, показание температуры и т. Д.). Нет смысла сообщать о вычислении до четырех значащих цифр, если ваш входной источник имеет точность только двух цифр.

NSDecimals и NSDecimalNumbers необходимы, когда вы хотите выполнить более расширенные вычисления для десятичных значений, но хотите избежать ошибок с плавающей запятой. Например, я использую их при выполнении высокоточных вычислений в моем приложении или если мне нужно каким-то образом манипулировать валютой. Из этих двух я придерживаюсь NSDecimal из соображений производительности , используя NSDecimalNumber в тех случаях, когда мне нужно взаимодействовать с Базовыми данными или импортировать числовые значения в структуры NSDecimal.

В этом случае кажется, что NSDecimal будет излишним, потому что вы на самом деле не настраиваете значения ползунка, просто отображаете их на экране. Если вам необходимо выполнить более поздние манипуляции (разрезать пополам, выполнить формулу и т. Д.), Я бы рекомендовал округлить ползунок до целочисленного представления, создать из него структуру NSDecimal, выполнить вычисления в виде NSDecimals, а затем использовать процедуры вывода строки для NSDecimal / NSDecimalNumber для отображения результата на экране. Затем вы можете легко сохранить вычисленное значение как NSDecimalNumber в Базовых данных или как строковое представление в SQLite или другом файле.

Кроме того, я бы не стал сильно беспокоиться о производительности при таких простых вычислениях, как этот, пока что-то вроде Инструментов не скажет вам, что они являются горячей точкой. Скорее всего, эти вычисления с NSDecimal и т. Д. Не будут.

...