Начнем с перечисленной иллюстрации. Компания хочет использовать минимальное количество запросов к онлайн-сервису. Они также хотят завершить работу в параллельном режиме, чтобы минимизировать общее время, не тратя процессоры в состоянии простоя.
Когда они используют два параллельных запроса, они обнаруживают, что в последнем раунде занят только один процессор, а это означает, что другой простаивает. Они решают использовать три процессора и равномерно распределяют количество запросов… к своему удивлению, они снова все равно находят один процессор в последнем раунде, в то время как два других простаивают. В следующий раз они используют четыре процессора, затем пять, шесть… снова в результате чего в последнем раунде занят только один процессор, все остальные тратятся впустую. Наконец-то они используют семь процессоров, и все они работают одинаково, без потерь цикла.
Итак, что мы можем здесь узнать о наименьшем количестве запросов?
Введение
Возможно, вы слышали о проблеме распределения монет, которая очень похожа на ту, которая описана в аннотации. Давайте кратко рассмотрим его:
При раздаченнколичества монет среди двух, трех, четырех, пяти или шести человек, остается одна монета. Но если их распределить между семью людьми, то они распределятся поровну. Аналогично и в упомянутой выше задаче о параллельном процессоре число запросов полностью делится только на семь; один запрос остается в последнем раунде, когда их два, три, четыре, пять или шесть.
Следующие условные выражения могут правильно проверить значение n:
( ( (n % 2) == (n % 3) == (n % 4) == (n % 5) == (n % 6) == 1 ) and (n % 7) == 0 )
Что %означает оператор по модулю? Это оператор модуля, который делит левую часть на правую и возвращает остаток ( а не частное). Нам нужно проверять натуральные числа, пока мы не достигнем значения, nпри котором вышеуказанное условие будет равно true. Мы можем сократить количество итераций за счет наименьшего общего кратного 2, 3, 4, 5и 6. Давайте придерживаться темы, а не примера.
Одним из наиболее распространенных примеров модуля является время на часах. Он продолжает округлять до наименьшего значения всякий раз, когда оно пересекает наибольшее значение. Например, после 59 минуты и секунды округляются до 0. Аналогично, значение часов становится 0 после 23 (для 24-часового формата) и 1 после 12 (для 12-часового формата). Чтобы реализовать ту же логику для минут и секунд в Python, мы можем сделать следующее:
var = var + 1 if (var == 60): var = 0
var = var + 1 var = var % 60
Аналогичным образом мы можем реализовать логику часовой части в зависимости от типа часов (12-часовые или 24-часовые).
Модуль — ценная операция в информатике.
Практическое использование % для начинающих
Говоря с новыми программистами Python, можно сказать, что оператор модуля обычно используется следующим образом:
- Независимо от того, является ли число четным или нечетным:
number % 2
возвращает ненулевое значение (True
), еслиnumber
оно нечетное. - Проверить, еслиНделится наМ:
N % M
возвращает значение0
, еслиN
оно делится наM
. - Проверить, еслиНкратноМ:
N % M
возвращает значение0
, еслиN
кратноM
. - Получите последнийМцифры числаН:
N % (10 ** M)
- Значения переноса (для индексов массива):
index = index % len(array)
могутindex
оставаться между0
иlen(array) - 1
, включительно. - Принуждение числа к определенному кратному:
tens = value - (value % 10)
- Ограничьте определенное значение:
hour % 24
возвращает число между0
и23
. - Побитовые операции:
x % 256
то же значение, что иx & 255
. - Обычно используется в хешировании:
h(k) = k % m
сопоставляет ключk
с одним изm
сегментов.
Программы, использующие оператор %
Следующие основные программы являются примерами других распространенных применений оператора модуля:
1. Возврат дроби вместо результата деления с десятичной точкой:
# frac (7, 3) returns (2,1,3) # frac (6, 3) returns (2,0,3) # frac (6,0) returns (None,0,0) def frac(n, d): if d==0: return (None, 0, d) return (n//d, n%d, d)
2. Преобразование прошедшего времени (указанного в секундах) в часы, минуты и секунды:
# time (5000) returns (1,23,20) # time (500) returns (0,8,20) # time (50) returns (0,0,50) def time(s): ss = s % 60 s //= 60 mm = s % 60 s //= 60 hh = s % 24 return (hh, mm, ss)
3. О прогрессе сообщается только раз внтчаснт чвремя прохождения цикла (чтобы делать что-то каждыйнтчаснт читерация, а не выполнение на каждой итерации):
# loop (70) prints 0,10,20,30,40,50,60,69 # loop (30) prints 0,10,29,29 # loop (15) prints 0,10,14 def loop(s): for i in range(s): if i%10 == 0: print(i,end=',') print(i)
4. Перестановка цифр в числе.
# rev (1579) returns 9751 # rev (234) returns 432 # rev (60) returns 6 def rev(n): r = 0 while n>0: d = n % 10 r = r * 10 + d n //= 10 return r
5. Преобразование целого числа в десятичной системе счисления в другую систему счисления:
# octa (255) returns 377 # octa (63) returns 77 # octa (7) returns 7 def octa(n): b = 8 t = 1 r = 0 while n>0: d = n % b r = t * d + r t = t * 10 n //= 8 return r
6. Преобразование линейного массива в матричную структуру:
# a1to2 ([10,20,30,40]) returns [[10, 20], [30, 40]] # a1to2 ([10,20,30,40,50]) returns [[10, 20], [30, 40], [50, 0]] # a1to2 ([10,20,30,40,50,60,70,80]) returns [[10, 20], [30, 40], [50, 60], [70, 80]] def a1to2(a1): s = len(a1) cols = int(s ** 0.5) rows = s // cols if rows*cols < s: rows = rows+1 print(rows,cols) a2 = [[0 for i in range(cols)] for j in range(rows)] for i in range(s): r = i // cols c = i % cols a2[r][c] = a1[i] return a2
7. Вычисление наибольшего общего делителя:
# gcd (12340,236) returns 4 # gcd (10,20) returns 10 # gcd (20,10) returns 10 def gcd(a,b): if (a>b): x,y = a,b else: x,y=b,a while y!=0: r = x % y x = y y = r return x
8. Вычисление наименьшего общего кратного:
# lcm (20,30) returns 60 # lcm (15,20) returns 60 # lcm (30,7) returns 210 def lcm(a,b): if (a>b): x,y = a,b else: x,y=b,a l = y while l % x > 0: l = l + y return l
9. Проверка того, является ли число простым или составным:
# is_prime (20) returns False # is_prime (19) returns True # is_prime (21) returns False def is_prime(n): if n<2: return False r = int(n**0.5)+1 for i in range(2,r): if n % i == 0: return False return True;
Модульная арифметика используется в теории чисел, теории групп и криптографии.
Особенности оператора % в Python
Математически всегда гарантируется, что
если q, r = divmod(n, d),
тогда q * d + r == n.
Получает divmod()число nи делитель dв качестве параметров и возвращает частное qи остаток rв качестве результатов. Знак остатка зависит от знака делителя:
- Положительный делитель дает положительный остаток.
- Отрицательный делитель дает отрицательный остаток.
В следующей таблице показано сравнение положительных и отрицательных делителей в Python, а также обоснование.
Учитывать | 21 % 4 равно 1 | 21% -4 это -3 |
Потому что | 21 // 4 == 5 | 21 // -4 == -6 |
Сравнивать | 5 * 4 + 1 == 21 | ( -6 ) * (-4) + ( -3 ) == 21 |
Поведение %for intvs.Decimal
Так что же делает оператор «%» по модулю для объектов десятичного типа? В Python результат оператора %для Decimalобъектов типа отличается от результата оператора % для простых целых чисел.
Знак числителя используется с результатом, когда Decimalобъект используется в качестве операнда. В противном случае используется знак знаменателя.
# Four combinations of Signs of numerator vs. denominator# for simple int values#using `%` operatorprint(«(21 % 4) is», 21 % 4) # 1print(«(21 % -4) is», 21 % -4) # -3print(«(-21 % 4) is», -21 % 4) # 3print(«(-21 % -4) is», -21 % -4) # -1print(«————————————————————«)#using `divmod()` functionq, r = divmod(21, 4)print(«divmod(21, 4) is», (q,r),» ===>> «,q,»*»,4,»+ «,r,»=»,21)q, r = divmod(21, -4)print(«divmod(21, -4) is», (q,r),» ===>> «,q,»*»,-4,»+»,r,»=»,21)q, r = divmod(-21, 4)print(«divmod(-21, 4) is», (q,r),» ===>> «,q,»*»,4,»+ «,r,»=»,-21)q, r = divmod(-21, -4)print(«divmod(-21, -4) is», (q,r),» ===>> «,q,»*»,-4,»+»,r,»=»,-21)
Знак остатка для простых целых чисел зависит от знаменателя.
В приведенном выше коде мы продемонстрировали изменение остатка из-за изменения знака знаменателя. В первой группе операторов используется %оператор, а в другой — divmod()функция для отображения частного для ясности значения остатка.
# Four combinations of Signs of numerator vs. denominator# for Decimal type objectsfrom decimal import Decimalfor i in range(9):print(Decimal(i) % Decimal(4),» , «,Decimal(-i) % Decimal(4),» , «,Decimal(i) % Decimal(-4),» , «,Decimal(-i) % Decimal(-4))
Знак остатка для десятичных объектов зависит от числителя.
В приведенном выше коде результат содержит знак числителя, использованного в выражении. Значение остатка получается из простых (беззнаковых) значений операндов без соблюдения правила q * d + r == n.
Будьте осторожны при использовании Decimalобъектов с %оператором в Python. Результат отличается от результата простых целых чисел.
Подведение итогов и дальнейшие действия
Оператор модуля в Python представлен оператором %. Существуют и другие встроенные функции, подобные этой, divmod()которые можно использовать для вычисления остатка в результате деления. Для простых целых чисел Python q * d + r == nгарантирует q, r = divmod(n, d). Результат оператора %отличается, если операнды являются объектами типа Decimal.