Коли ви використовуєте float і коли ви використовуєте double


194

Часто в своєму досвіді програмування мені потрібно приймати рішення, чи слід використовувати float або double для моїх реальних цифр. Іноді я ходжу за поплавком, іноді йду на подвійний, але справді це відчувається більш суб’єктивно. Якби я зіткнувся із захистом свого рішення, я, мабуть, не надавав обґрунтованих причин.

Коли ви використовуєте float і коли ви використовуєте double? Ви завжди використовуєте подвійний, лише коли є обмеження на пам’ять, ви переходите до плавання? Або ви використовуєте завжди float, якщо тільки вимога точності не вимагає, щоб ви використовували подвійний? Чи є деякі суттєві відмінності щодо обчислювальної складності основної арифметики між поплавком і подвійним? Які плюси і мінуси використання float або double? А ти навіть довгий подвійний використовував?


28
У багатьох випадках ви хочете використовувати жоден, а скоріше десятковий тип з плаваючою чи фіксованою точкою. Бінарні типи з плаваючою комою не можуть точно представляти більшість десяткових знаків.
CodesInChaos

3
Пов’язано з тим, що викликає помилки округлення плаваючої точки? . @CodesInChaos моя відповідь пропонує ресурси, які допоможуть вам визначитися з цим рішенням. Не існує рішення, яке відповідає всім розмірам .
Марк Бут

Дуже хороша відповідь знайдена в: Переповнення стека
Haris

5
Що саме ви маєте на увазі під десятниками. Якщо вам потрібно точно представити такі значення, як 0,01 (скажімо, на гроші), то (двійкові) з плаваючою комою не є відповіддю. Якщо ви просто маєте на увазі не цілі числа, то швидше за все з плаваючою комою - але тоді "десятковий знак" - не найкраще слово для опису того, що вам потрібно.
Кіт Томпсон

1
Ви не завжди маєте вибору. Наприклад, на платформі Arduino як подвійний, так і плаваючий прирівнюються до плавання. Вам потрібно знайти додаткову бібліотеку для обробки справжніх пар.
ківірон

Відповіді:


187

Вибір за замовчуванням для типу з плаваючою комою повинен бути double. Це також тип , який ви отримуєте з плаваючою точкою литералов без суфікса або (в C) стандартні функції , які працюють з числами з плаваючою точкою (наприклад exp, sinі т.д.).

float слід використовувати лише в тому випадку, якщо вам потрібно працювати з великою кількістю чисел з плаваючою комою (думати в порядку тисяч і більше), і аналіз алгоритму показав, що зменшений діапазон і точність не представляють проблеми.

long doubleможе використовуватися, якщо вам потрібен більший діапазон або точність, ніж doubleякщо це передбачено на вашій цільовій платформі.

Таким чином, floatі long doubleповинні бути зарезервовані для використання фахівцями, з doubleдля «кожен день» використання.


10
Я, мабуть, не вважав би плаваючим на кілька тисяч значень, якщо б не виникли проблеми з продуктивністю, пов'язаними з кешуванням плаваючої точки та передачею даних. Здійснення аналізу зазвичай суттєво коштує, щоб показати, що float є досить точним.
Патрісія Шанахан

4
Як додаток, якщо вам потрібна сумісність з іншими системами, може бути вигідним використання тих же типів даних.
zzzzBov

15
Я б використовував поплавці для мільйонів чисел, а не 1000. Крім того, деякі графічні процесори краще використовувати плавці, в цьому спеціалізованому випадку використовують поплавці. Ще, як ви кажете, використовуйте парні.
user949300

4
@PatriciaShanahan - «проблема продуктивності, пов’язана з ..» Хороший приклад - якщо ви плануєте використовувати SSE2 або подібні векторні інструкції, ви можете робити 4 ops / вектор у поплавці (проти 2 на подвійний), що може значно підвищити швидкість ( вдвічі більше операційних та половина даних для читання та запису). Це може значно знизити поріг, коли використання поплавців стає привабливим, і варто розібратися з розбіркою числових питань.
greggo

12
Я схвалюю цю відповідь ще однією додатковою порадою: коли для опрацювання значень RGB для відображення є прийнятним використання float(а іноді і з половинною точністю), оскільки ні людське око, ні дисплей, ні кольорова система не мають стільки бітів точності . Ця порада застосовується для скажімо OpenGL тощо. Ця додаткова порада не стосується медичних зображень, які мають більш суворі вимоги до точності.
rwong

42

Рідко є причина використовувати float замість подвійного в коді, орієнтованому на сучасні комп'ютери. Додаткова точність знижує (але не усуває) ймовірність помилок округлення або іншої неточності, що спричинить проблеми.

Основні причини, з якими я можу подумати використовувати float, це:

  1. Ви зберігаєте великі масиви чисел і вам потрібно зменшити споживання пам'яті програми.
  2. Ви орієнтуєтесь на систему, яка не підтримує плаваючу крапку з подвійною точністю. До недавнього часу багато графічних карт підтримували лише плаваючі крапки з одною точністю. Я впевнений, що є безліч потужних та вбудованих процесорів, які також мають обмежену підтримку з плаваючою комою.
  3. Ви орієнтуєтесь на обладнання, де одноточна швидша, ніж подвійна точність, і ваш додаток широко використовує арифметику з плаваючою комою. На сучасних процесорах Intel, я вважаю, що всі обчислення з плаваючою комою проводяться в подвійній точності, тому ви нічого не отримуєте тут.
  4. Ви робите низькорівневу оптимізацію, наприклад, використовуючи спеціальні інструкції процесора, які працюють на декількох номерах одночасно.

Таким чином, в основному подвійний - це шлях, якщо ви не маєте апаратних обмежень або якщо аналіз не показав, що зберігання подвійних точних цифр істотно сприяє використанню пам'яті.


2
"Сучасні комп'ютери", що означають процесори Intel x86. Деякі машини, які використовували Древні, забезпечували абсолютно адекватну точність з основним типом поплавця. (CDC 6600 використовував 60-бітове слово, 48 біт нормалізованої мантіси з плаваючою комою, 12 біт експонента. Це ЗАДАЛЬНО те, що дає x86 для подвійної точності.)
Джон Р. Стром

@ John.R.Strohm: погодився, але компілятори C не існували на CDC6600. Це був Фортран IV ...
Базиль Старинкевич

Під «сучасними комп’ютерами» я маю на увазі будь-який процесор, побудований за останнє десятиліття або два, чи справді, оскільки стандарт IEEE з плаваючою точкою широко впроваджувався. Я прекрасно знаю, що існують архітектури, що не є x86, і мав це на увазі своєю відповіддю - я згадав про графічні процесори та вбудовані процесори, які, як правило, не x86.
користувач611910

Це просто неправда, хоча. SSE2 може маніпулювати 4 поплавками або 2 дублями за одну операцію, AVX може маніпулювати 8 поплавцями або 4 парними, AVX-512 може маніпулювати 16 поплавцями або 8 парними. Для будь-якого виду обчислень з високою продуктивністю, математику на плавках слід вважати вдвічі швидшою за одну і ту ж операцію на подвоєннях на x86.
Ларрі Гріц

1
І це навіть гірше, тому що ви можете вмістити вдвічі більше плаваючих елементів у кеш-пам'яті процесора, ніж удвічі, а затримка пам’яті, ймовірно, буде головним вузьким місцем у багатьох програмах. Зберігання цілого робочого набору поплавців теплим у кеші може бути буквально на порядок швидше, ніж використання подвійних та їх розлив до ОЗУ.
Ларрі Гріц

10

Використовуйте doubleдля всіх своїх розрахунків і тимчасових змінних. Використовуйте, floatколи вам потрібно підтримувати масив чисел - float[](якщо точність достатня), і ви маєте справу з десятками тисяч floatчисел.

Багато / більшість математичних функцій або операторів конвертують / повертають double, і ви не хочете повертати цілі до floatбудь-яких проміжних кроків.

Наприклад, якщо у вас є вхід 100 000 чисел з файлу або потоку і вам потрібно сортувати їх, поставте цифри у float[].


5

Деякі платформи (ARM Cortex-M2, Cortex-M4 тощо) не підтримують подвійну функцію (це завжди можна перевірити в посібнику з вашого процесора. Якщо немає попереджень або помилок щодо компіляції, це не означає, що код є оптимальним. подвійне можна наслідувати.). Ось чому вам може знадобитися дотримуватися int або float .

Якщо це не так, я б використовував подвійний .

Ви можете перевірити відому статтю Д. Голдберга («Що повинен знати кожен вчений-комп’ютер про арифметику з плаваючою комою»). Ви повинні подумати двічі, перш ніж використовувати арифметику з плаваючою комою. Є досить великий шанс, що вони взагалі не потрібні у вашій конкретній ситуації.

http://perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf


3
На це питання вже досить добре відповіли рік тому ... але в будь-якому випадку, я б сказав, що коли ви використовуєте подвійний на платформах з подвоєним прискоренням FPU, вам слід використовувати його на будь-яких інших, навіть якщо це означає дозволяючи компілятору імітувати його замість того, щоб використовувати FPU лише з плаваючою комою (зауважте, що FPU також не потрібні на всіх платформах. Насправді архітектура Cortex-M4 визначає їх як додаткову функцію [був M2 типовою?] ).
Selali Adobor

Ключ до цієї логіки полягає в тому, що, правда, слід атрибувати арифметику з плаваючою комою, і це багато "химерностей", безумовно, не беручи до участі в підтримці FPU для пар, що означає просто використовувати пар, а не поплавці. Поплавки в цілому швидше, ніж удвічі, і займають менше пам’яті (функції FPU відрізняються). Обсяг використання перешкоджає цьому моменту передчасної оптимізації. Як і факт, подвійна велика кількість надмірних програм (можливо, навіть більшості). Чи дійсно для елементів на цій сторінці потрібно, щоб їх відносні положення та розміри були обчислені до 13 знаків після коми?
Selali Adobor

2
Коли ви включаєте посилання на сторінку чи документ, що знаходиться поза сайтом, скопіюйте відповідну інформацію чи резюме з документа у свою відповідь. Посилання поза сайтом мають тенденцію зникати з часом.
Адам Цукерман

3

Для проблем із реальним світом важливий поріг вибірки ваших даних, відповідаючи на це питання. Так само важлива і шумова підлога. Якщо вибраний тип даних перевищить будь-яке, користь від підвищення точності не принесе.

Більшість пробовідбірників у реальному світі обмежені 24-бітним ЦАП. Припускаючи, що 32 біти точності на обчисленнях у реальному світі повинні бути адекватними там, де значення і 24 біт точності.

Подвійна точність поставляється ціною в 2 рази. Тому обмеження використання подвійних елементів на плавках може різко скоротити слід / пропускну здатність пам’яті запущених програм.


-3

Вибір, яку змінну використовувати між float та double, залежить від точності необхідних даних. Якщо потрібна відповідь, щоб мати незначну різницю від фактичної відповіді, кількість потрібних знаків після коми буде численною, і таким чином буде продиктовано, що цей подвійний буде використаний. Flolo відрубає частину десяткових знаків, зменшивши точність.


3
Ця відповідь не додає нічого нового до питання і не може сказати нічого фактичного використання.
Martijn Pieters

-5

Зазвичай я використовую floatтип, коли мені не потрібна велика точність - наприклад, для грошей - що неправильно, але це те, що я звик неправильно робити.

З іншого боку, я використовую, doubleколи мені потрібна більша точність, наприклад для складних математичних алгоритмів.

Стандарт C99 говорить про це:

Існує три типи плаваючої точки: плаваюча, подвійна та довга подвійна. Подвійний тип забезпечує принаймні стільки точності, скільки поплавця, а довгий тип подвійний забезпечує принаймні стільки точності, скільки і подвійний. Набір значень float типу - це підмножина набору значень типу double; набір значень типу double є підмножиною набору значень типу long double.

Я ніколи насправді не використовував long double, але не використовую C / C ++ так сильно. Зазвичай я використовую динамічно набрані мови на зразок Python, де вам не потрібно дбати про типи.

Для отримання додаткової інформації про Double vs Float дивіться це запитання на сторінці SO .


25
Використання плаваючої точки для серйозних грошових розрахунків - це, мабуть, помилка.
Барт ван Іґен Шенау

17
float - це неправильний тип грошей. Вам потрібно використовувати максимально можливу точність.
ChrisF

8
@BartvanIngenSchenau Плаваюча точка для грошей зазвичай нормальна, двійкова плаваюча точка - ні. Наприклад, .net Decimal- це тип з плаваючою комою, і це, як правило, хороший вибір для розрахунків грошей.
CodesInChaos

13
@ChrisF Вам не потрібна "висока точність" грошей, потрібні точні значення.
Sean McSomething

2
@SeanMcSomething - Справедлива точка. Однак поплавці все-таки є неправильним типом, хоча, враховуючи типи плаваючої точки, доступні для більшості мов, вам потрібна "висока точність", щоб отримати "точні значення".
ChrisF
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.