Які переваги та недоліки використання одного замість іншого в C ++?
Які переваги та недоліки використання одного замість іншого в C ++?
Відповіді:
Якщо ви хочете знати справжню відповідь, вам слід прочитати те, що повинен знати кожен асистент з питань арифметики з плаваючою крапкою .
Коротше кажучи, хоча і double
дозволяє підвищити точність у своєму поданні, для певних обчислень це призведе до більших помилок . «Правильним» вибором є: використовуйте стільки точності, скільки вам потрібно, але не більше, і вибирайте правильний алгоритм .
Багато компіляторів у будь-якому випадку роблять розширену математику з плаваючою комою в "несуворому" режимі (тобто використовують ширший тип з плаваючою комою, доступний в апаратному забезпеченні, наприклад, 80-бітові та 128-бітові плаваючі), це також слід враховувати. На практиці ви навряд чи можете помітити різницю в швидкості - вони все одно є вихідцями з обладнання.
double
- це в більшості випадків безпечніше.
Якщо у вас немає певних причин вчинити інакше, використовуйте подвійний.
Можливо, що дивно, але саме подвійний, а не плаваючий тип є "звичайним" типом з плаваючою комою в C (і C ++). Стандартні математичні функції, такі як гріх і журнал, беруть дублі в якості аргументів і повертають дублі. Звичайний літерал із плаваючою комою, як, наприклад, коли ви пишете 3.14 у програмі, має тип double. Не плавати.
На типових сучасних комп'ютерах подвоєння може бути настільки ж швидким, як плаваючий, або навіть швидшим, тому продуктивність, як правило, не є фактором, який слід враховувати, навіть для великих розрахунків. (І це повинні бути великі обчислення, або продуктивність навіть не повинна входити вам у голову. Мій новий настільний комп’ютер i7 може зробити шість мільярдів множень вдвічі за одну секунду.)
Відповісти на це питання неможливо, оскільки в ньому немає контексту. Ось кілька речей, які можуть вплинути на вибір:
Реалізація компілятора з поплавками, парними та довгими парними. Стандарт С ++ говорить:
Існує три типи з плаваючою комою: плаваюча, подвійна та довга подвійна. Тип double забезпечує принаймні таку саму точність, як float, а тип long double забезпечує щонайменше стільки ж точності, як і double.
Отже, усі три можуть мати однаковий розмір у пам’яті.
Наявність FPU. Не всі центральні процесори мають FPU, і іноді типи з плаваючою комою емулюються, а іноді типи з плаваючою комою просто не підтримуються.
Архітектура ФПУ. FPU IA32 внутрішньо 80-бітний - 32-бітні та 64-бітні плаваючі пристрої розширюються до 80-бітових при завантаженні та зменшуються при зберіганні. Існує також SIMD, який може робити чотири 32-бітові плаваючі параметри або два 64-бітові плаваючі паралельно. Використання SIMD не визначене в стандарті, тому для цього потрібен компілятор, який робить більш складний аналіз, щоб визначити, чи можна використовувати SIMD, або вимагає використання спеціальних функцій (бібліотек або власних даних). Результатом 80-бітного внутрішнього формату є те, що ви можете отримати дещо різні результати залежно від того, як часто дані зберігаються в оперативній пам'яті (таким чином, втрачаючи точність). З цієї причини компілятори не особливо оптимізують код з плаваючою комою.
Пропускна здатність пам'яті. Якщо для подвійного потрібно більше місця для зберігання, ніж для плаваючого, читання даних займе більше часу. Це наївна відповідь. На сучасному IA32 все залежить від того, звідки беруться дані. Якщо це в кеш-пам'яті L1, навантаження незначне, якщо дані надходять з одного рядка кешу. Якщо воно охоплює більше одного рядка кешу, є невеликі накладні витрати. Якщо це з L2, це займає деякий час довше, якщо це в оперативній пам'яті, то це ще довше і, нарешті, якщо це на диску, це величезний час. Тож вибір float або double є менш важливим, ніж спосіб використання даних. Якщо ви хочете зробити невеликий розрахунок для безлічі послідовних даних, кращий невеликий тип даних. Багато обчислень на невеликому наборі даних дозволить вам використовувати більші типи даних із будь-яким значним ефектом. Якщо ви' при повторному доступі до даних дуже випадково, тоді вибір розміру даних є неважливим - дані завантажуються в сторінки / рядки кешу. Отже, навіть якщо вам потрібен лише байт з оперативної пам'яті, ви можете отримати 32 передані байти (це дуже залежить від архітектури системи). Крім усього цього, CPU / FPU може бути суперскалярним (він же конвеєрний). Отже, навіть незважаючи на те, що навантаження може зайняти кілька циклів, CPU / FPU може бути зайнятий чимось іншим (наприклад, множенням), що приховує час завантаження до певної міри.
Стандарт не застосовує жодного конкретного формату для значень з плаваючою комою.
Якщо у вас є специфікація, це допоможе вам вибрати оптимальний варіант. В іншому випадку, це не означає, що використовувати.
Double є більш точним, але кодується на 8 байтів. float - це всього 4 байти, тому менше місця і менша точність.
Ви повинні бути дуже обережними, якщо у вашому додатку є дубль та плаваюча версія. У мене була помилка через це в минулому. Одна частина коду використовувала float, а решта коду використовувала double. Копіювання double в float, а потім float в double може спричинити помилку точності, яка може мати великий вплив. У моєму випадку це була хімічна фабрика ... сподіваємось, це не мало суттєвих наслідків :)
Я думаю, що саме через цю помилку ракета Ariane 6 вибухнула кілька років тому !!!
Подумайте добре про тип, який буде використовуватися для змінної
Це залежить від того, як компілятор реалізує double. Це дозволено, щоб double і float були однаковими (і це є в деяких системах).
З огляду на це, якщо вони справді різні, головним питанням є точність. Подвійний має набагато вищу точність завдяки різниці в розмірах. Якщо числа, які ви використовуєте, зазвичай перевищують значення плаваючого числа, тоді використовуйте подвійне.
Кілька інших людей згадували питання про ефективність. Це було б останнє в моєму списку міркувань. Правильність повинна бути вашим фактором No1.
Використовуйте ту точність, яка потрібна для досягнення відповідних результатів . Якщо тоді ви виявите, що ваш код працює не так добре, як хотілося б (ви правильно використали профілювання?), Подивіться на:
Думаю, незалежно від відмінностей (на які, як зазначають усі, поплавці займають менше місця і взагалі швидше) ... хто-небудь коли-небудь страждає на проблеми продуктивності за допомогою подвійного? Я кажу, використовуйте double ... і якщо згодом ви вирішите "нічого собі, це дійсно повільно" ... знайдіть вузьке місце у вашій продуктивності (що, мабуть, не факт, що ви використовували double). ПОТІМ, якщо це все ще занадто повільно для вас, подивіться, де ви можете пожертвувати деякою точністю і скористатися плаваючою системою.
Основна різниця між поплавком та подвійним - це точність. У Вікіпедії є більше інформації про одинарну точність (плаваюча) та подвійну точність .
Це дуже залежить від центрального процесора, найбільш очевидні компроміси між точністю та пам'яттю. З ГБ оперативної пам'яті пам’ять не становить великих проблем, тому, як правило, краще використовувати double
s.
Що стосується продуктивності, то вона сильно залежить від центрального процесора. float
s зазвичай отримує кращу продуктивність, ніж double
s, на 32-бітній машині. На 64 бітах double
s іноді швидші, оскільки це (зазвичай) власний розмір. Тим не менш, що буде мати значення набагато більше, ніж ваш вибір типів даних, - чи можна скористатися перевагами інструкцій SIMD на своєму процесорі чи ні.
double має вищу точність, тоді як плаваючі забирають менше пам'яті і швидші. Як правило, слід використовувати флоат, якщо у вас немає випадку, коли він недостатньо точний.