Вы скорее всего знаете, что существуют не только текстовые файлы. Различные форматы данных предусматривают специальное кодирование. Например, BMP изображения хранят некоторую заголовочную информацию и цвета всех пикселей в виде чисел.
Давайте поработаем с такими данными. Нам дают файл в некотором формате, назовем его NUM. Он содержит список 2-байтных чисел. Для простоты будем считать, что отрицательных чисел не существует.
Напишите программу, которая вычисляет сумму всех записанных в файле чисел в 2-байтном диапазоне.
Формат ввода
В файле numbers.num содержатся числа в указанном формате.
Формат вывода
Одно число — сумма всех чисел в файле на 2-байтном диапазоне.
Примечание
Для простоты файлы в примерах записаны в HEX формате. В этом виде файл представляется как последовательность четырехзначных шестнадцатеричных чисел.
В первом примере записано 5 шестнадцатеричных чисел: 1, 2, 3, 4, 5. Их сумма равна 15.
Во втором — 255 и 257. Их сумма равна 512.
Файл из примеров в изначальном виде можно загрузить здесь:
Если вы хотите изучить принцип хранения целых чисел в ЭВМ, советуем почитать про прямой, обратный и дополнительный коды.
Пример
Ввод
# ВНИМАНИЕ СОДЕРЖИМОЕ НАСТОЯЩЕГО ФАЙЛА ДРУГОЕ
0001 0002 0003 0004 0005
Вывод
15
Ввод
# ВНИМАНИЕ СОДЕРЖИМОЕ НАСТОЯЩЕГО ФАЙЛА ДРУГОЕ
00FF 0101
Вывод
512
Решение
Очень простая линейная задача на освоение чтения данных из бинарных файлов.
И в то же время, в материалах к заданиям не упомянуты ряд аспектов. Например не рассказано как открыть файл в двоичном режиме, не расказано как прочитать два байта,упоминаются символы, но для начинающих программистов не очевидно что символ в этой терминологии эквивалентен байту. Да и кодировка UTF-8 добавляет сумятицы, потому что в ней символ может быть и два и три байта. Все это начит что надо изучить документацию на методы open() и read(). Кроме того, чтобы последовательность двух байт превратить в целое число необходимо прочитать про методы и параметры функции int(), в плане порядка байтов и его беззнаковости.
Другая сложность – понять правильно требование в условии вывода. Дело в том, что часто “2-байтный диапазон” относят к числам, которые читают из файла, а не интерпретируют как “отбросьте старшие разряды у ответа так, чтобы ответ “влез в два байта”. Но как бы то ни было, именно эта простая вещь скрывается за мудреной и неоднозначной фразой.
Поэтому открываем файл в решиме двоичного чтения, читаем порциями по два байта, каждую порцию конвертируем в число с помощью функции int.from_bytes() и накапливаем в результат.
После того, как все данные прочитаны делим результат на 65536 по модулю и выводим остаток.
Посмотреть код
Решение
file_in = 'numbers.num'
sum = 0
with open(file_in, 'rb') as file:
while (chunk := file.read(2)):
sum += int.from_bytes(chunk)
print(sum % 0x10000) # 65535