Чи має поплавок 32 двійкові цифри, а подвійний - 64 двійкові цифри? Документація була надто складною, щоб зрозуміти її.
Чи всі біти перекладаються на значущі цифри? Або розташування десяткової коми займає деякі біти?
Чи має поплавок 32 двійкові цифри, а подвійний - 64 двійкові цифри? Документація була надто складною, щоб зрозуміти її.
Чи всі біти перекладаються на значущі цифри? Або розташування десяткової коми займає деякі біти?
Відповіді:
float : 32 біти (4 байта), де 23 біти використовуються для мантиси (близько 7 десяткових цифр). Для експоненти використовується 8 бітів, тому плаваючий засіб може «переміщати» десяткову крапку вправо або вліво, використовуючи ці 8 бітів. Це дозволяє уникнути зберігання великої кількості нулів у мантисі, як у 0,0000003 (3 × 10 -7 ) або 3000000 (3 × 10 7 ). В якості знакового біта використовується 1 біт.
double : 64 біти (8 байт), де 52 біти використовуються для мантиси (приблизно 16 десяткових цифр). Для експоненти використовується 11 бітів, а 1 біт - знаковий біт.
Оскільки ми використовуємо двійкові (лише 0 та 1), один біт у мантисі має неявний 1 (як float, так і double використовують цей фокус), коли число не дорівнює нулю.
Крім того, оскільки все є у двійковому (мантисі та експонентах) перетворення в десяткові числа, як правило, не є точними. Такі числа, як 0,5, 0,25, 0,75, 0,125 зберігаються точно, але 0,1 - ні. Як казали інші, якщо вам потрібно точно зберігати центи, не використовуйте float або double, використовуйте int, long, BigInteger або BigDecimal.
Джерела:
http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers
double
і 7,2 для float
, тобто 15 і 7. Деякі більші числа можуть бути представлені в кожному випадку, і жодне з них не відноситься до дробів, але в ньому немає "середнього значення", і жодне з ваших джерел не говорить інакше.
Довга відповідь:
Числа з плаваючою комою мають три складові:
По суті, це вдається sign * 2^exponent * (1 + fraction)
. «Розмір» числа, його показника, для нас не має значення, оскільки він лише масштабує значення частки частки. Знаючи, що log₁₀(n)
дає число цифр n
, †, ми можемо визначити точність числа з плаваючою точкою за допомогою log₁₀(largest_possible_fraction)
. Оскільки кожен біт у поплавці зберігає 2 можливості, двійкове число n
бітів може зберігати число до 2ⁿ - 1
(загальна кількість 2ⁿ
значень, де одне із значень дорівнює нулю). Це стає трохи волосатішим, оскільки виявляється, що числа з плаваючою комою зберігаються з одним бітом дробу менше, ніж вони можуть використовувати, оскільки нулі представлені спеціально, а всі ненульові числа мають принаймні один ненульовий двійковий біт. ‡
Поєднуючи це, цифри точності для числа з плаваючою точкою складають
log₁₀(2ⁿ)
, де n
- кількість бітів частки числа з плаваючою точкою. 32-розрядний поплавок має 24 біти дробу для ≈7,22 десяткових цифр точності, а 64-бітний подвійний - 53 біти дробу для ≈15,95 десяткових цифр точності.
Щоб отримати докладнішу інформацію про точність із плаваючою точкою, ви можете прочитати про концепцію машини epsilon .
† n ≥ 1
Принаймні - для інших чисел ваша формула буде виглядати більше
⌊log₁₀(|n|)⌋ + 1
.
‡ “Це правило по-різному називають умовою провідного біта, неявною умовою бітів або умовою прихованих бітів”. ( Вікіпедія )
Зі специфікації Java :
Типи з плаваючою комою бувають з плаваючою комою та подвійними, які концептуально пов’язані зі значеннями та операціями IEEE 754 з одноточною 32-бітною та подвійною точністю 64-бітного формату, як зазначено у IEEE Standard for Binary Floating-Point Arithmetic, ANSI / IEEE Стандарт 754-1985 (IEEE, Нью-Йорк).
Оскільки важко щось робити із числами, не розуміючи основ IEEE754, ось ще одне посилання .
Важливо розуміти, що точність не є рівномірною і що це не точне зберігання чисел, як це робиться для цілих чисел.
Приклад :
double a = 0.3 - 0.1;
System.out.println(a);
відбитки
0.19999999999999998
Якщо вам потрібна довільна точність (наприклад, для фінансових цілей), вам може знадобитися Big Decimal .
Звичайна математична відповідь.
Зрозумівши, що число з плаваючою точкою реалізується як деякі біти, що представляють показник ступеня, а решта, більшість із цифр (у двійковій системі), можна мати таку ситуацію:
З великим показником, скажімо, 10²³, якщо міняється найменш значущий біт, з’являється велика різниця між двома сусідніми роздільними мишучими числами. Крім того, десяткова точка бази 2 робить так, що багато чисел 10 базових значень можна лише наблизити; 1/5, 1/10 - нескінченні числа.
Так загалом : числа з плаваючою комою не слід використовувати, якщо ви дбаєте про значні цифри. Для грошових сум із розрахунком, e, a, найкраще використовувати BigDecimal .
Для фізики подвійні числа з плаваючою комою є достатніми, плаваючі майже ніколи. Крім того, частина процесорів із плаваючою комою, FPU, може навіть використовувати трохи більшу точність внутрішньо.
Числа з плаваючою комою кодуються за допомогою експоненціальної форми, тобто щось подібне m * b ^ e
, тобто зовсім не подібне до цілих чисел. Запитання, яке ви задаєте, було б значущим у контексті фіксованих точок . Доступні численні арифметичні бібліотеки з фіксованою точкою .
Щодо арифметики з плаваючою точкою: Кількість десяткових цифр залежить від подання та системи числення. Наприклад, є періодичні числа ( 0.33333
), які не мають скінченного подання у десятковому вигляді, але мають двійкове і навпаки.
Також варто відзначити , що числа з плаваючою точкою до певної точки дійсно є різниця більше , ніж один, тобто value + 1
виходи value
, так як value + 1
не можуть бути закодовані з використанням m * b ^ e
, де m
, b
і e
фіксуються в довжину. Те саме відбувається для значень, менших за 1, тобто всі можливі кодові точки не мають однакової відстані.
Через це не існує точності саме n
цифр, як у номерах фіксованих точок, оскільки не кожне число з n
десятковими цифрами має кодування IEEE.
Існує майже обов'язковий документ, який ви тоді повинні прочитати, який пояснює числа з плаваючою крапкою: Що кожен знавець інформатики повинен знати про арифметику з плаваючою крапкою .
Подивіться на Float.intBitsToFloat
і Double.longBitsToDouble
, який вид пояснює, як біти відповідають числам із плаваючою комою. Зокрема, шматочки нормального float
виглядають приблизно так
s * 2^exp * 1.ABCDEFGHIJKLMNOPQRSTUVW
де A ... W - це 23 біти - 0s та 1s - що представляють дріб у двійковому файлі - s дорівнює +/- 1, представлене 0 або 1 відповідно, а exp є 8-бітовим цілим числом із підписом.