Вопрос-ответ

How many significant digits do floats and doubles have in java?

Сколько значащих цифр имеют плавающие и двойные значения в Java?

У числа с плавающей запятой 32 двоичных разряда, а у double 64 двоичных разряда? Документация была слишком сложной для понимания.

Все ли биты преобразуются в значащие цифры? Или расположение десятичной точки занимает часть битов?

Переведено автоматически
Ответ 1

float: 32 бита (4 байта), где 23 бита используются для мантиссы (около 7 десятичных разрядов). для показателя степени используется 8 бит, поэтому число с плавающей запятой может “перемещать” десятичную точку вправо или влево, используя эти 8 бит. Это позволяет избежать хранения большого количества нулей в мантиссе, как в 0.0000003 (3 × 10-7) или 3000000 (3 × 107). В качестве знакового бита используется 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

http://en.wikipedia.org/wiki/Binary64

http://en.wikipedia.org/wiki/Binary32

Ответ 2

32-разрядное значение с плавающей запятой имеет точность около 7 цифр, а 64-разрядное значение double - около 16 цифр

Длинный ответ:

Числа с плавающей запятой состоят из трех компонентов:


  1. Знаковый бит, определяющий, является ли число положительным или отрицательным.

  2. Показатель степени для определения величины числа.

  3. Дробь, которая определяет, насколько далеко находится число от двух значений экспоненты. Иногда это называется “значение, мантисса или коэффициент”

По сути, это работает до sign * 2^exponent * (1 + fraction). “Размер” числа, его экспонента, для нас не имеет значения, потому что он только масштабирует значение дробной части. Зная, что log₁₀(n) дает количество цифр в n,† мы можем определить точность числа с плавающей запятой с помощью log₁₀(largest_possible_fraction). Поскольку каждый бит с плавающей запятой хранит 2 возможности, двоичное число n битов может хранить число до 2ⁿ - 1 (общее количество 2ⁿ значений, где одно из значений равно нулю). Это становится немного сложнее, потому что оказывается, что числа с плавающей запятой хранятся с одним битом дроби меньшим, чем они могут использовать, потому что нули представлены особым образом и все ненулевые числа имеют по крайней мере один ненулевой двоичный бит.‡

В совокупности получается, что цифры точности для числа с плавающей запятой равны log₁₀(2ⁿ), где n - количество битов дроби числа с плавающей запятой. 32-разрядный float содержит 24 бита дроби для ≈7,22 десятичных разрядов точности, а 64-разрядный double содержит 53 бита дроби для ≈15,95 десятичных разрядов точности.

Чтобы узнать больше о точности с плавающей запятой, вы, возможно, захотите прочитать о концепции машинного эпсилона.


† Для n ≥ 1 по крайней мере — для других чисел ваша формула будет больше похожа на ⌊log₁₀(|n|)⌋ + 1.

‡ “Это правило по-разному называется соглашением о начальных битах, соглашением о неявных битах или соглашением о скрытых битах”. (Википедия)

Ответ 3

Из спецификации java :


Типами с плавающей запятой являются float и double, которые концептуально связаны со значениями и операциями 32-разрядного формата с одинарной точностью и 64-разрядного формата с двойной точностью IEEE 754, как указано в Стандарте IEEE для двоичной арифметики с плавающей запятой, ANSI / IEEE Standard 754-1985 (IEEE, Нью-Йорк).


Поскольку трудно что-либо делать с числами, не понимая основ IEEE754, вот другая ссылка.

Важно понимать, что точность неравномерна и что это не точное хранение чисел, как это делается для целых чисел.

Пример :

double a = 0.3 - 0.1;
System.out.println(a);

С принтами

0.19999999999999998

Если вам нужна произвольная точность (например, для финансовых целей), вам может понадобиться большая десятичная дробь.

Ответ 4

Обычный математический ответ.

Понимая, что число с плавающей запятой реализовано в виде нескольких битов, представляющих экспоненту, а остальные, в основном для цифр (в двоичной системе), возникает следующая ситуация:

При высоком показателе, скажем, 1023, если изменить младший значащий бит, появляется большая разница между двумя соседними различимыми числами. Кроме того, десятичная точка с основанием 2 означает, что многие числа с основанием 10 могут быть только приблизительными; 1/5, 1/10 - бесконечные числа.

Итак, в общем: числа с плавающей запятой не следует использовать, если вас интересуют значащие цифры. Для денежных сумм с вычислением e, a лучше всего использовать BigDecimal.

Для физики удвоений с плавающей запятой достаточно, чисел с плавающей запятой почти никогда. Более того, часть процессоров с плавающей запятой, FPU, может даже использовать немного большую точность внутри.

java