Чтобы понять диапазон значений и точность вычислений float и double, сначала нужно понять, как десятичные дроби хранятся в компьютерах:

Например: 78.375 — положительное десятичное число. Чтобы сохранить это число в компьютере, его нужно представить в формате с плавающей запятой. Сначала выполним преобразование в двоичную систему:

P.S.: Двоичная точка отличается от десятичной точки. После двоичной точки идут отрицательные степени 2; после десятичной точки — отрицательные степени 10.

1. Двоичное преобразование десятичных чисел (чисел с плавающей запятой)

Целая часть числа 78.375:

Дробная часть:

Итак, двоичная форма числа 78.375 — 1001110.011

Затем, используядвоичную научную нотацию,получаем

Обратите внимание, что после преобразования число, представленное в двоичной научной нотации, имеет основание, экспоненту и дробную часть. Это называетсячислом с плавающей запятой.


2. Хранение чисел с плавающей запятой в компьютерах

В компьютерах для хранения этого числа используется представление с плавающей запятой, которое делится на три основные части:

Первая часть используется для хранениязнакового бита,используемого для различения положительного и отрицательного. Здесь он равен 0, что указывает на положительное число.

Вторая часть используется для храненияэкспоненты,здесь экспонента равна 6 в десятичной системе.

Третья часть используется для хранениядробной части,здесь дробная часть равна 001110011.

Обратите внимание, что экспонента также может быть положительной или отрицательной; это будет рассмотрено позже.

Как показано на рисунке ниже:

Например, тип float занимает 32 бита и использует представление чисел с плавающей запятой одинарной точности:

Бит знака занимает 1 бит и используется для представления положительных и отрицательных чисел.

Биты экспоненты занимают 8 бит и используются для представления экспоненты.

Биты дробной части занимают 23 бита и используются для представления дробной части, при этом недостающие биты заполняются 0.

Тип double занимает 64 бита и использует представление чисел с плавающей запятой двойной точности:

Бит знака занимает 1 бит, биты экспоненты занимают 11 бит, а биты дробной части занимают 52 бита.

На этом этапе уже можно смутно заметить, что:

Биты экспоненты определяют диапазон значений,потому что чем больше значения, которые могут представлять биты экспоненты, тем больше числа, которые можно представить!

Биты дробной части определяют точность вычислений,потому что чем больше числа, которые могут представлять биты дробной части, тем выше точность вычислений!

Возможно, это всё ещё недостаточно ясно, поэтому давайте рассмотрим примеры:

float имеет только 23 бита дробной части, т. е. 23 двоичных бита. Максимальное десятичное число, которое он может представить, — это 2 в 23-й степени, что равно 8,388,608, т. е. 7 десятичных цифр. Строго говоря, точность может гарантировать вычисления только с 6 десятичными цифрами со 100% уверенностью.

double имеет 52 бита дробной части, что соответствует максимальному десятичному значению 4,503,599,627,370,496. Это число содержит 16 цифр, поэтому точность вычислений может гарантировать только 15 десятичных цифр вычислений со 100% уверенностью.

P.S.: Обычные научные калькуляторы, например используемые в старшей школе, обычно поддерживают максимум 15 цифр вычислений; за этим пределом точности недостаточно. В реальном программировании тип double также используется чаще, потому что он может гарантировать 15 цифр вычислений. Если требуется ещё более высокая точность вычислений, необходимы другие типы данных, например BigDecimal в Java, который поддерживает вычисления с более высокой точностью.


3. Смещение битов экспоненты и беззнаковое представление

Обратите внимание, что экспонента может быть отрицательной или положительной, то естьэкспонента — это целое число со знаком.Вычисления с целыми числами со знаком сложнее, чем с беззнаковыми целыми числами. Поэтому, чтобы уменьшить ненужные сложности, при фактическом сохранении экспоненты её нужно преобразовать вбеззнаковое целое число.Так как же выполняется преобразование?

Обратите внимание, что часть экспоненты у float составляет 8 бит, поэтому диапазон экспоненты — от -126 до +127. Чтобы исключить влияние отрицательных чисел на фактические вычисления (такие как сравнения, сложение и вычитание и т. д.), при фактическом сохранении к экспоненте можно применить простое сопоставление, добавивсмещение.Например, смещение для экспоненты float равно 127, поэтому отрицательные числа не появляются.

Например:

Если экспонента равна 6, фактически сохраняется 6+127=133, т. е. 133 преобразуется в двоичный вид и затем сохраняется.

Если экспонента равна -3, фактически сохраняется -3+127=124, т. е. 124 преобразуется в двоичный вид и затем сохраняется.

Когда нам нужно вычислить фактическое десятичное число, которое представлено, просто вычтите смещение из экспоненты.

Для соответствующего типа double смещение экспоненты при хранении равно 1023.


4. Наконец

Итак, чтобы сохранить десятичную дробь 78.375 с помощью типа float, сначала нужно преобразовать её в число с плавающей точкой, получивбит знака,иэкспоненту,идробную часть.Этот пример уже был разобран выше, поэтому:

Бит знака равен 0, биты экспоненты — 6+127=133, чьё двоичное представление — 10 000 101, а дробная часть — 001110011. Пожалуйста, автоматически дополните недостающую часть нулями 0.

Соединённые вместе и представленные как float, часть, выделенная жирным, — это биты экспоненты, а крайний левый бит — это бит знака 0, обозначающий положительное число:

0 10000101 001110011 00000 00000 0000

Если использовать double для его хранения... посчитайте сами; там слишком много нулей.

Автор: Boss呱呱

Ссылка: https://www.zhihu.com/question/46432979/answer/221485161