В Go существует 2 типа для выражения чисел с плавающей точкой.
// Диапазон: от -3.4028235e+38 до +3.4028235e+38
// В памяти: 4 байта.
type float32 float32
// Диапазон: от -1.7976931348623157e+308 до +1.7976931348623157e+308
// В памяти: 8 байт.
type float64 float64Хранение числе с плавающей точкой, а также арифметические операции с ними в Go, реализованы по стандарту IEEE 754(a.k.a IEC 60559).
Основные составляющие числа с плавающей точкой в соответствии со стандартом:
- Знак числа (S): первый бит показывает положительное число или отрицательное.
- Экспонента (E): показатель степени, на которую умножается основание (в двоичном представлении это 2). Иными словами, экспонента определяет порядок числа: на сколько число большое или маленькое.
- Мантисса (M): часть числа, представляющая его значащие цифры. Иными словами точность числа.
(−1)s×M×2E
формула представления числа с плавающей запятой по стандарту IEEE-754
| Компонент | Биты float32 | Биты float64 |
|---|---|---|
| Знак | 1 | 1 |
| Экспонента | 8 | 11 |
| Мантисса | 23 | 52 |
| максимальное точно представимое целое число | 224 | 253 |
Почему максимальное точно представимое целое для float32 = 2²⁴, хотя мантиса занимает 23 бита?
У float32 мантисса хранится в 23 битах, но реальная точность — 24 бита, так как по стандарту IEEE-754 автоматически добавляется скрытый старший бит = 1.
16 777 216
максимально точно представимое целое 224
Важно понимать, что при превышении этого числа мы столкнемся с неожиданным поведением:
Что выведет данный код и почему?
fmt.Println(float32(16777216) == float32(16777217)) - Число 16 777 217 требует 25‑го бита, так как не помещается в мантиссу float32;
- Оно будет округлено до числа ближайшего к данному, которое float32 может представить;
- В нашем случае это будет 16777216
Рассмотрим еще один пример:
Что выведет данный код и почему?
fmt.Println(float32(16_777_216) == float32(16_777_219))- Число 16 777 219 требует 25‑го бита, так как не помещается в мантиссу float32;
- Оно будет округлено до числа ближайшего к данному, которое float32 может представить;
- В нашем случае это будет 16 777 220
ULP=2E−23
формула округления числа до ближайшего
- E — реальная степень двойки числа
- 23 — количество явных бит мантиссы
- Скрытый бит добавляет 1 к точности, но на ULP влияет только экспонента
Что это обозначает на практике?
- Чем больше E, тем больше шаг между числами
- Каждый “новый бит” экспоненты удваивает шаг
| Пример числа | E (степень) | ULP = шаг | Комментарий |
|---|---|---|---|
| 16 777 216 ≈ 2²⁴ | 24 | 2^(24-23)=2 | шаг = 2 |
| 28 777 218 ≈ 2²⁵ | 25 | 2^(25-23)=4 | шаг = 4 |
| 60 000 000 ≈ 226 | 26 | 2^(26-23)=8o | шаг = 4 |
| 2³⁰ | 30 | 2^(30-23)=128 | шаг = 128 |
Какие проблемы возникают при работе с вещественными числами, а также методы их решения мы рассмотрим в следующих разделах.
Leave a Reply