Коли використовувати float vs decimal


14

Я будую цей API, і база даних зберігатиме значення, які представляють одне з наступних:

  • процент
  • середній
  • ставка

Я, чесно кажучи, не маю уявлення, як зобразити щось, що в діапазоні становить від 0 до 100%. Чи має бути

  • 0,00 - 1,00
  • 0,00 - 100,00
  • будь-яка інша альтернатива, яку я не знаю

Чи є чіткий вибір для цього? Глобальний спосіб представлення на базах даних щось, що становить від 0 до 100%? Подальше, який правильний для нього тип, float або decimal?

Дякую.



5
Цифри можуть зберігатися різними способами. Немає нічого поганого в тому, щоб зберігати відсоток, використовуючи 0-100, або використовувати 0-1. Важливо те, що вам потрібно робити з цифрами, яка точність вам потрібна тощо. Ви повинні пояснити більше контексту, перш ніж можна дати хорошу відповідь. Чи потрібно зберігати номери, які точно представлені, з невеликою кількістю десяткових цифр? Якщо ви середні речі, ви отримаєте дроби, такі як третина чи сьома. Чи потрібно їх точно зберігати? Або просто приблизно? Як приблизно? Що ти будеш робити з ними?
Eric Eric Postpischil

1
Якщо значення від 0,00 до 100,00 з кроком 0,01, це 10001 різних значень. Просто використовуйте знак intдля представлення сотих або в одиницях Перміріади або ‱.
chux

@ chux-ReinstateMonica - Так, "масштабовані цілі числа" можливі, але незграбні.
Рік Джеймс

@RickJames Можливо. Я не вважаю масштабні цілі числа важкими.
chux

Відповіді:


4

Я прийму протилежну позицію.

FLOATпризначений для приблизних чисел, таких як відсотки, середні показники тощо. Ви повинні виконати форматування під час відображення значень або в коді програми, або за допомогою FORMAT()функції MySQL.

Ніколи не тестуйте float_value = 1.3; Є багато причин, чому це не вдасться.

DECIMALслід використовувати для грошових цінностей. DECIMALдозволяє уникнути повторного округлення, коли значення необхідно округлювати до доларів / центів / євро / тощо. Бухгалтери не люблять фракцій центів.

Реалізація MySQL DECIMALдозволяє отримати 65 значущих цифр; FLOATдає приблизно 7 і DOUBLEприблизно 16. 7 зазвичай більш ніж достатньо для датчиків і наукових обчислень.

Щодо "відсотка" - іноді я використовував, TINYINT UNSIGNEDколи хочу споживати лише 1 байт сховища і мені не потрібно великої точності; іноді я використовував FLOAT(4 байти). Немає типу даних, налаштованих спеціально для відсотків. (Зауважте також, що DECIMAL(2,0)це значення не може утримувати 100, тому технічно вам знадобиться DECIMAL(3,0).)

Або іноді я використовував FLOATкоефіцієнт, який утримував значення від 0 до 1. Але тоді мені потрібно переконатись у множенні на 100, перш ніж відобразити "відсоток".

Більше

Всі три "відсоткові, середні, швидкісні" пахнуть плаваючими, так що це був би мій перший вибір.

Один критерій прийняття рішення про тип даних ... Скільки копій значення буде існувати?

Якщо у вас є таблиця в мільярд рядків зі стовпцем на відсоток, вважайте, що TINYINTце займе 1 байт (1 Гб), але FLOATзайме 4 байти (4 ГБ). Щодо іншого, у більшості застосунків не так багато рядків, тому це може не бути актуальним.

Як "загальне" правило, "точні" значення повинні використовувати певну форму INTабо DECIMAL. Неточні речі (наукові розрахунки, квадратні корені, поділ тощо) повинні використовувати FLOAT(або DOUBLE).

Крім того, форматування виводу зазвичай слід залишити на передньому кінці програми. Тобто, хоча "середній" може обчислюватись "14.6666666 ...", на дисплеї повинно бути щось на зразок "14.7"; це дружніше для людей. Тим часом у вас є основне значення, щоб згодом вирішити, що "15" або "14.667" є кращим вихідним форматуванням.

Діапазон "0,00 - 100,00" можна виконати або FLOAT використовувати формат виводу або використовувати DECIMAL(5,2)(3 байти) з попереднім визначенням, що ви завжди хочете вказаної точності .


3

Я б зазвичай рекомендував не використовувати float. Числа з плаваючою комою представляють числа в базовій-2, що призводить до того, що деякі (точні) числа є округлими в операціях або порівняннях, оскільки вони просто не можуть бути точно збережені в базі-2. Це може призвести до пригнічуючої поведінки.

Розглянемо наступний приклад :

create table t (num float);
insert into t values(1.3);

select * from t;

| num |
| --: |
| 1.3 |

select * from t where num = 1.3;

| num |
| --: |

Базове порівняння кількості 2 1.3не вдається. Це хитро.

Для порівняння, десяткові забезпечують точне подання кінцевих чисел у межах їх діапазону. Якщо ви перейдете floatдо decimal(2, 1)наведеного вище прикладу, ви отримаєте очікувані результати.


4
Ця відповідь є помилковою у кількох аспектах. "Для порівняння, десяткові мають менший діапазон, але дають точне подання кінцевих чисел у межах цього діапазону" помилково: Десяткові не представляють ⅓ точно. "Деякі (точні, кінцеві) числа є округлими" невірно; цифри не є "округлими". Конверсії та інші операції можуть обійтись. Режим округлення за замовчуванням - це найчастіше круглий-найближчий-рівний, а не округлий.
Eric Eric Postpischil

4
Питання з точністю пов'язані не з "числами з плаваючою комою", а просто з числовими поданнями. Усі кінцеві числові подання мають обмежену точність: плаваюча точка, фіксована точка, ціле число, раціональне, десяткове, двійкове і все.
Eric Eric Postpischil

2
Зітхнути. Що ви виправили? У моєму коментарі відповідь неправильна, оскільки в ній десятковий розмір забезпечує точне подання чисел у межах його діапазону, але насправді це не так, тому що не дає точного подання of. Зміна говорить "точне" замість "точного", але тоді, чому двійкова плаваюча точка не є такою ж хорошою - і не є точною для ⅓, і обидві, або ні точні, залежно від того, який ваш поріг для точності і наскільки точність вони мають. Питання вказує, що середні показники будуть представлені, а усереднення трьох речей дає вам цифри на зразок ⅓.
Eric Eric Postpischil

4
У коментарі йдеться про те, що найчастіше використовується круглий-найближчий-до-рівний, але у відповіді все ще йдеться про округлення. У відповіді сказано, що порівняння може збігатися, але порівняння є ідеальним: порівняння завжди повертають математично правильний результат, без округлення. (Деякі мови програмування можуть конвертувати операнди перед порівнянням, але це окремі операції.)
Eric Postpischil

1
1/3 не може бути точно представлена ​​ні двійковою, ні десятковою. Знижка у розмірі 20% від 14,99 дол. Вимагатиме заокруглення дробових центів не існувати.
Рік Джеймс

0

Різниця між поплавком і десятковим є точністю. Десяткові знаки можуть на 100% точно представляти будь-яке число в точності десяткового формату, тоді як Float не може точно представити всі числа.

Використовуйте Десяткове значення, наприклад, пов'язане з фінансовим значенням, і використовуйте float для, наприклад, графічного значення


0

Я рекомендую використовувати, decimal(5,2)якщо ви збираєтесь зберігати його таким же чином, як і ви будете його відображати, оскільки decimalце для збереження точної точності. (Див. Https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html )

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

( https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html )

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

Для стовпців DECIMAL MySQL виконує операції з точністю до 65 десяткових цифр, що повинно вирішити найпоширеніші проблеми неточності.

https://dev.mysql.com/doc/refman/8.0/en/problems-with-float.html


0

Десяткові. Для фінансових застосувань краще використовувати типи Decimal, оскільки це забезпечує високий рівень точності та легко уникнути помилок округлення

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

Float: Він використовується в основному у графічних бібліотеках, оскільки дуже високі вимоги до потужностей обробки, а також використовуються ситуації, які можуть зазнати помилок округлення.

Довідка: http://net-informations.com/q/faq/float.html


0
mysql> create table numbers (a decimal(10,2), b float);
mysql> insert into numbers values (100, 100);
mysql> select @a := (a/3), @b := (b/3), @a * 3, @b * 3 from numbers \G

*********************************************************************

@a := (a/3): 33.333333333
@b := (b/3): 33.333333333333
@a + @a + @a: 99.999999999000000000000000000000
@b + @b + @b: 100

Десятковий робив саме те, що повинен був робити в цих випадках, він усікав решту, тим самим втрачаючи 1/3 частини.

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

Сподіваюся, це допоможе.


0

У tsql: Float, 0.0 зберігається як 0, і його не потрібно визначати після цифри після коми, наприклад, вам не потрібно писати Float (4,2). Десяткові, 0,0 зберігають як 0,0, і він має можливість визначити як десятковий (4,2), я б запропонував 0,00-1,00, зробивши це, ви можете обчислити значення цього відсотка без множення на 100, і якщо ви повідомлите, то встановіть тип даних цього стовпця у відсотках, як MS Excel та інші види платформи 0.5 -> 50%.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.