Вы скорее всего знаете, что существуют не только текстовые файлы. Различные форматы данных предусматривают специальное кодирование. Например, 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
Здравствуйте, Ваше решение не проходит ни один тест ни проходит. Данное решение не проходит третий тест, единственную подсказку я нашел, что нужно отбрасывать старшие байты
with open(‘numbers.num’, ‘rb’) as file:
values = []
while True:
bytes_chunk = file.read(2)
if not bytes_chunk:
break
values.append(int.from_bytes(bytes_chunk, ‘big’))
print(sum(values))
В тексте решения была опечатка в имени файла. Поправил. Спасибо, что обратили внимание.
Чтобы Ваше решение заработало, нужно добавить в него проверку:
Почему нужно делить именно на 6536, понимаю что это степень двойки, но почему именно это число?
2 ** 8 = 256
2 ** 16 = 65 536
получается, что это количество чисел которое можно записать с помощью двух байт. по совместительству это один из самых простых способов отбросить значения, попавшие в третий и более старший байты.