У Marcus Zarra есть довольно ясная позиция по этому: , "Если Вы имеете дело с валютой вообще, тогда необходимо использовать NSDecimalNumber". Его статья вдохновила меня изучать NSDecimalNumber, и я был очень впечатлен им. Ошибки плавающей точки IEEE при контакте с основой, 10 математики раздражала меня некоторое время (1 * (0.5 - 0.4 - 0.1) =-0.00000000000000002776) и NSDecimalNumber, покончили с ними.
NSDecimalNumber только добавляет другого немного цифр двоичной точности с плавающей точкой, он на самом деле основывает 10 математики. Это избавляется от ошибок как один показанный в примере выше.
Теперь, я пишу символьное математическое приложение, таким образом, мое требование 30 + точность десятичной цифры и никакие странные ошибки с плавающей точкой могли бы быть исключением, но я думаю, что на это стоит посмотреть. Операции являются немного более неловкими, чем простой var = 1 + 2 математики стиля, но они все еще управляемы. Если Вы волнуетесь по поводу выделения всех видов экземпляров во время Ваших математических операций, NSDecimal является структурой C, эквивалентной из NSDecimalNumber и существуют функции C для того, чтобы сделать те же самые математические операции с ним. По моему опыту, они - много быстро для всех кроме большинства требовательных приложений (3 344 593 дополнения/с, 254 017 подразделений/с на MacBook Air, 281 555 дополнений/с, 12 027 подразделений/с на iPhone).
Как добавленная премия, descriptionWithLocale NSDecimalNumber: метод предоставляет строке локализованную версию числа, включая корректный десятичный разделитель. То же идет наоборот для его initWithString:locale: метод.
На практике может быть достаточно использовать массив (вектор) и отложить затраты на вставку и удаление.
Удалить элемент, пометив его как удаленный, вставить элемент в корзину в желаемой позиции и запомнить смещение для больших индексов.
Вставки и удаления будут очищать O (1) плюс O (N) в удобное время; поиск будет иметь значение O (1) в среднем, O (количество изменений с момента последней очистки) в худшем случае.
Не существует абстрактного типа данных со сложностью O (1) для вставки, стирания и поиска, который также обеспечивает итератор двунаправленного доступа .
Изменить:
Это верно для произвольно большого домена. Учитывая достаточно маленький домен, вы можете реализовать набор со сложностью O (1) для Insert, Стирание и поиск и итератор двунаправленного доступа с использованием массива и двусвязного списка:
std::list::iterator array[MAX_VALUE];
std::list list;
Инициализация:
for (int i=0;i<MAX_VALUE;i++)
array[i] = list.end();
Вставка:
if (array[value] != list.end())
array[value] = list.insert(value);
Стереть:
if (array[value] != list.end()) {
array[value].erase();
array[value] = list.end();
}
Поиск:
array[value] != list.end()
tr1's unordered_set
(also available in boost) is probably what you are looking for. You don't specify whether or not you want a sequence container or not, and you don't specify what you are using to give O(1) lookup (ie. vectors have O(1) lookup on index, unordered_set mentioned above has O(1) average case lookup based on the element itself).
Associative arrays (hashtable) have O(1)
lookup complexity, while doubly linked lists have O(1)
bidi iteration.
Вы не сможете уместить все свои требования в один контейнер ... что-то нужно дать;) Однако, может быть, вам это интересно: http://www.cplusplus.com/reference/stl/
Полный список всех гарантий сложности для STL можно найти здесь:
Каковы гарантии сложности стандартных контейнеров?
Резюме:
Есть контейнеры, которые обеспечивают ограниченную гарантию вставки
Стереть
Поиск:
Итак, ответ основан на типах контейнеров.
This is what the standard gurantees are defiend for how does this translate to real containers:
std::vector: Sequence, Back Sequence, Forward/Reverse/Random Container
std::deque: Sequence, Front/Back Sequence, Forward/Reverse/Random Container
std::list: Sequence, Front/Back Seuqence, Forward/Reverse Container
std::set: Sorted/Simple/Unique Associative Container, Forward Container
std::map: Sorted/Pair/Unique Associative Container, Forward Container
std::multiset: Sorted/Simple/Multiple Associative Container, Forward Container
std::multimap: Sorted/Pair/Multiple Associative Container, Forward Container
Одна уловка, которую я сделал, когда возился с оптимизацией хранилища, - это реализовать связанный список с добавлением O (1) [1], а затем выполнить операцию кэширования, которая предоставляет структуру с более быстрый поиск O (n) [2]. Фактический кеш создается за O (n) времени, и я не сосредоточился на стирании. Так что я немного «схитрил» и переложил работу на другую операцию. Но если вам не нужно делать кучу добавлений / удалений, это неплохой способ сделать это.
[1] Сохранить указатель конца и добавлять только в конец. Обход не требуется.
[2] Я создал динамический массив [3] и провел поиск по нему. Поскольку данные не были отсортированы, я не мог использовать binsearch против них в течение O (lg n) времени. Хотя, полагаю, я мог бы его отсортировать.
[3] Массивы имеют лучшую производительность кеширования, чем списки.