Ломается расчет времени
Моя задача высчитать время из секунд
Я написал такой код:
def pretty_time(raw):
if raw % 60 != raw:
s = raw % 60
m = raw // 60
if m % 60 != m:
h = s // 60
m %= 60
s = m % 60
pretty = f'{h}ч {m}м {s}с'
else:
pretty = f'{m}мин, {s} сек'
else:
pretty = f'{raw} сек'
return pretty
На вид все должно работать правильно?
Так и есть, но после проверки оказалось что...
if __name__ == '__main__':
for _ in range(10):
print(pretty_time(int(input(''))))
5
5 сек
59
59 сек
60
1мин, 0 сек
700
11мин, 40 сек
7777
0ч 9м 9с
3600
0ч 0м 0с
86400
0ч 0м 0с
1
1 сек
555
9мин, 15 сек
10000
0ч 46м 46с
Не понимаю, как так могло выйти?
Python 3.10rc2
Ответы (3 шт):
Ошибка в алгоритме, конечно же!
def pretty_time(raw):
if raw % 60 != raw:
s = raw % 60 # s всегда меньше 60!!!
m = raw // 60
if m % 60 != m:
h = s // 60 # если число меньше 60 разделить на 60, то целая часть всегда будет 0
Т.е. мало того, что количество часов вычисляется не из общего количества секунд, а из того количества секунд, которое не уместилось в целую минуту, так еще и само это вычисление происходит неправильно.
Я вижу 2 ошибки:
- В коде
h = s // 60- а надоh = m // 60. Часы ведь от минут вычисляются. - И второй раз
s = m % 60испортит вам секунды. Эту (второй раз встречающуюся) строку вообще надо выкинуть из кода.
Итого вся функция должна выглядеть как-то так:
def pretty_time(raw):
if raw >= 60:
s = raw % 60
m = raw // 60
if m >= 60:
h = m // 60
m %= 60
pretty = f'{h}ч {m}м {s}с'
else:
pretty = f'{m}мин, {s}сек'
else:
pretty = f'{raw} сек'
return pretty
Если не нужно выводить элементы времени с нулевыми значениями, то можно вот так:
def pretty_time(raw):
if not raw: return '0 сек'
time_values = []
for div,text in ((60, 'сек'), (60, 'мин'), (24, 'ч'), (raw, 'д')):
v = raw % div
if v: time_values.append(f'{v} {text}')
raw //= div
return ' '.join(time_values[::-1])
Вообще в таких вычислениях лучше не считать сущности отдельно, а попытаться как-то универсально их обрабатывать, тогда заведомо меньше ошибок будет в коде. Например, если обрабатывается время не больше, чем сутки, то можно использовать такой код, поскольку часы, минуты и секунды вычисляются по совершенно одинаковому алгоритму - выводим остаток от деления, потом делим нацело и т.д.:
def pretty_time(raw):
res = ''
for t in 'смч':
res = f'{raw % 60}{t} {res}'
raw //= 60
if raw == 0:
break
print(res)
pretty_time(59)
pretty_time(555)
pretty_time(10000)
Вывод:
59с
9м 15с
2ч 46м 40с
Но и для бОльших количеств времени можно использовать похожий алгорим, только нужно будет перебирать не только единицы времени, но и одновременно величину делителя для получения этих единиц. Алгоритм чуть усложнится, но останется таким же универсальным.