Представление действительных чисел

Данный листок посвящен проблеме записи дробных чисел в двоичной системе счисления и представлению действительных чисел в памяти компьютера.

Для получения двоичного представления числа типа float можно использовать метод hex типа float, который возвращает текстовую строку с 16-ричным представлением числа типа float. Но этот метод не дает полного представления о формате хранения чисел типа float.

Для представления действительных чисел с плавающей точкой стандарт IEEE 754 определяет несколько различных форматов хранения числа, из которых наиболее распространенными в настоящий момент являются числа одинарной точности (4 байта), двойной точности (8 байт) и расширенной точности (10 байт). В языке Python числа типа float соответствуют числам двойной точности стандарта IEEE 754.

Для чисел типа float есть возможность получить точное двоичное представление числа. Для этого можно использовать функцию pack из модуля struct. Пример:

import struct
val = 0.1
res = struct.pack('d', val)

Объект res имеет тип bytes, этот тип используется для хранения двоичных данных в виде последовательности байт. Количество байт в объекте можно вычислить при помощи функции len, к конкретному байту можно обратиться по индексу.

Пример использования модуля struct для получения представления числа типа float в двоичной и шестнадцатеричной системах счисления.

import struct
val = 0.1
b = struct.pack('d', val)
HEX = ""
BIN = ""
for elem in b[::-1]:
    HEX += hex(elem)[2:].rjust(2, '0') + " "
    BIN += bin(elem)[2:].rjust(8, '0') + " "
print(HEX)
print(BIN)

Упражнения

A: Двоичную дробь в десятичную

Дано неотрицательное число, записанное в виде двоичной дроби: запись содержит только цифры 0 и 1 и, возможно, точку. Запись числа содержит не более 30 символов. Переведите это значение в величину типа float и выведите результат.

Ввод Вывод
11.01
3.25
100
4
0.111111
0.984375

B: Десятичную дробь в двоичную

Дано действительное неотрицательное число, не превосходящее 100, записанное в десятичном виде с фиксированной точкой. Необходимо представить его в виде двоичной дроби с фиксированной точкой и вывести это представление. Ответ должен отличаться от верного не более, чем на 2-32 степени, поэтому необходимо вывести не менее 32 двоичных цифр после точки.

Ввод Вывод
3.25
11.01
4
100
0.1
0.00011001100110011001100110011001100110011

C: Двоичную периодическую дробь в десятичное число

Дана запись двоичной периодической дроби, которая включает в себя:

  1. Необязательную целую часть.
  2. Обязательный символ точки, отделяющий целую часть от дробной.
  3. Необязательную дробную непериодическую часть.
  4. Необязательную периодическую дробную часть, записываемую в круглых скобках.

Переведите значение этой дроби в величину типа float и выведите результат. Общая длина входной строки не превосходит 30 символов.

Ввод Вывод
0.(01)
0.33333333333333
11.01
3.25
10.0(101)
2.357142857143

D: Рациональную дробь в двоичную периодическую

Дано рациональное число. Запишите его в виде двоичной периодической дроби.

На вход программа получает два натуральных числа n и m, каждое из которых не превосходит 1000. Программа должна вывести значение n/m, записанное в виде двоичной периодической дроби, при этом длина непериодической дробной части и длина периода должны быть минимально возможными. Если данное число является конечной двоичной дробью, периодическую часть выводить не надо.

Формат вывода двоичной дроби соответствует предыдущей задаче.

Ввод Вывод
1 3
0.(01)
13 4
11.01
5 14
0.0(101)

E: Двоичную периодическую дробь в рациональное число

Дана запись двоичной периодической дроби. Необходимо представить ее в виде несократимой рациональной дроби n/m. Программа должна вывести значения n и m.

Ввод Вывод
0.(01)
1 3
11.01
13 4
0.0(101)
5 14

F: a + b == c

Даны три действительных числа: a, b, c. Проверьте, выполняется ли равенство a+b=c. Если равенство выполняется, выведите YES, если не выполняется, выведите NO.

Числа a, b, c — действительные, положительные, не превосходят 10 и заданы не более, чем с 7 знаками после точки.

Ввод Вывод
2
3
7
NO
0.1
0.2
0.3
YES

G: Утренняя пробежка - 1

Подобную задачу вы решали два года назад...

В первый день спортсмен пробежал x километров, а затем он каждый день увеличивал пробег на 70% от предыдущего значения. По данному числу y определите номер дня, на который пробег спортсмена составит не менее y километров.

На вход программа получает два числа x и y. Числа положительные, действительные, не превосходят 1000, заданы с точностью до шести знаков после запятой.

Программа должна вывести единственное целое число.

Ввод Вывод
10 30
4

H: Утренняя пробежка - 2

И такая задача решалась...

В первый день спортсмент пробежал x километров, а затем он каждый день увеличивал пробег на 70% от предыдущего значения.

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

На вход программа получает два числа x и y. Числа положительные, действительные, не превосходят 1000, заданы с точностью до шести знаков после запятой.

Программа должна вывести единственное целое число.

Ввод Вывод
10 100
4

I: Диета

В некоторой сверхсекретной лаборатории изучаются физические возможности животных. Любой живой организм нуждается в трех компонентах пищи —белках, жирах и углеводах. Известен набор продуктов, имеющийся в распоряжении лаборатории и меню животных — сколько единиц каждого продукта они получают. Известно также, сколько белков, жиров и углеводов необходимо для нормальной жизнедеятельности животного. Необходимо определить, получает ли животное достаточное количество питательных веществ.

Известно, что животному требуется в сутки \(X\) белков, \(Y\) жиров и \(Z\) углеводов. Известно также, что всего животное получает в сутки \(N\) продуктов питания, и для каждого из них известны \(A_i\), \(B_i\), \(C_i\) и \(Q_i\) — соответственно энергетическая ценность единицы продукта в белках, жирах и углеводах и количество единиц этого продукта.

В первой строке входных данных записаны числа \(X\), \(Y\) и \(Z\) (действительные неотрицательные числа, не превосходящие 25000, заданные с точностью до 5 знаков после точки). Во второй строке записано целое неотрицательное число \(N\), не превосходящее 25000. Далее на \(N\) строках записаны соответственно \(A_i\), \(B_i\), \(C_i\) и \(Q_i\) (действительные неотрицательные числа, не превосходящие 100, заданные с точностью до 5 знаков после точки).

Выведите YES, если данный пищевой рацион является достаточным по всем параметрам и NO в противном случае.

Задача должна быть решена с использованием арифметики чисел типа float.

Ввод Вывод
1.0 1.0 1.0
3
1 0 0 1
0 0.5 0 2
0 0 0.25 4
YES

J: Машинное эпсилон

Напомним, что машинным эпсилоном называется такое наименьшее положительное число \(\varepsilon\), представимое в данном типе, что \(1+\varepsilon\neq1\). Значение машинного эпсилон зависит от типа данных, используемого для представления действительных чисел. Например, для чисел одинарной точности машинное эпсилон равно \(2^{-23}\).

Напишите программу, которая вычисляет машинное эпсилон для чисел двойной точности, соответствующих типу float в языке Python. Решение не должно использовать какие-либо специальные знания о формате хранения действительного числа (например, о размере мантиссы числа).

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

Проверка будет осуществляться путем сравнением ответов с правильными с относительной погрешностью 1%.

Пример

Вывод в данном примере содержит ответ для чисел одинарной точности, ваша программа должна выводить другой ответ.

Ввод Вывод
 
1.1920928955078125e-07

K: Наименьшее положительное число

В арифметике действительных чисел есть наименьшее положительное представимое число. Например, для действительных чисел одинарной точности это число равно \(2^{-149}\).

Напишите программу, которая вычисляет наименьшее представимое положительное число для чисел двойной точности, соответствующих типу float в языке Python.

Входные данные в этой задаче отсутствуют. Программа вывести одно действительное число.

L: Наибольшее целое представимое число

В каждом из действительных типов есть такое положительное целое число \(M\), что все целые положительные числа, не превосходящие \(M\) представимы в этом типе, а число \(M+1\) уже непредставимо. Например, для действительных чисел одинарной точности это значение равно 224=16777216, число 16777217 в виде действительного числа одинарной точности непредставимо.

Напишите программу, которая определяет наибольшее целое число, представимое в виде действительного числа двойной точности, соответствующего типу float в языке Python.

Входные данные в этой задаче отсутствуют. Программа вывести одно действительное число.

M: Наибольшее представимое число

В каждом из действительных типов данных есть наибольшее положительное число, представимое в этом типе. Например, для действительных чисел одинарной точности это число равно \(2^{128}-2^{104}\).

Вывыдите наибольшее положительное представимое число для чисел двойной точности, соответствующих типу float в языке Python.

N: Специальные числа

Используя только арифметические операции с типом float получите константы 0, -0, inf, -inf, nan и выведите их на экран.

Ввод Вывод
 
0.0
-0.0
inf
-inf
nan