0. ã¯ããã«
Pythonã§ã¹ãä¹ã»çޝä¹ãèšç®ããã«ã¯ïŒã€ã®æ¹æ³ããããŸãã
äŸãã° $3^4$ ãèšç®ããå Žåã
3 ** 4pow(3,4)
ã®ã©ã¡ãã§ãèšç®ã§ããŸãã1
æ¬èšäºã§ã¯ãããã®éãã«ã€ããŠèª¬æããŸãã
å 容ã¯ïŒç« æ§æã§ä»¥äžã®éãã§ãã
第ïŒç«     ïŒïŒãšpow()ã®éã
ãã®ç« ã§ã¯äž»ã«Pythonåå¿è ã察象ã«ïŒã€ã®æ¹æ³ã®éãã«ã€ããŠèª¬æããŸãã
第ïŒç«     éåºŠã®æ¯èŒ
ãã®ç« ã§ã¯ç«¶æããã°ã©ãã³ã°ãªã©ã®çç±ã§èšç®éåºŠãæ±ããæ¹ã察象ã«ïŒã€ã®æ¹æ³ã®å®è¡æéãæ¯èŒããçµæã説æããŸãã
第ïŒç«     Pythonå éšã®ã¯ãªã
ãã®ç« ã§ã¯ç¬¬ïŒç« ã§èŠãçµæã®çç±ãç¥ãããæ¹ã察象ã«ããããã®æ¹æ³ã§Pythonå éšã§è¡ãããŠããããšã説æããŸãã
1. ïŒïŒãšpow()ã®éã
ãã®ç« ã§ã¯Pythonã®åºæ¬äºé ãå«ãïŒã€ã®æ¹æ³ã®éãã説æããŸãã
1.1. Pythonå ã§ã®ç«å Ž
ïŒçªã®å€§ããªéãã¯Pythonå ã§ã®ç«å Žã§ããå ·äœçã«ãããš
-
**ã¯æŒç®å -
pow()ã¯é¢æ°
ã§ãã
æŒç®åã¯æŒç®ãè¡ãæç€ºã§ ** ã¯ãã¹ãä¹ãšããæŒç®ãããããšããæå³ããããŸãã
+, %, !=, andãªã©ãå
šãŠæŒç®åã§ãã
颿°ã¯æŒç®åãªã©ãçšããŠè¡ãäžé£ã®åŠçããŸãšãããã®ã§ããpow()ã¯ãã¹ãä¹èšç®ãè¡ãããšãã颿°ãªã®ã§ä»¥äžã®ã³ãŒããšäžç·ã ãšæã£ãŠããã°è¯ãã§ãããã
def pow(a, b):
result = a ** b
return result
1.2. 第3ã®åŒæ°
å°ãçºå±çãªå
容ãšãªããŸãããpow()颿°ã«ã¯ç¬¬3ã®åŒæ°ããããæŽæ°ãæå®ããããšãã§ããŸãã
ãããæå®ããå Žåãã¹ãä¹ã®çµæãæå®ããæŽæ°ã§å²ã£ãããŸããåŸãããŸããæå®ããªãã£ãå Žåã¯ããã©ã«ãã§Noneãèšå®ãããŠããã®ã§åç¯ã§èŠãéãã§ãããªãã第3ã®åŒæ°ãæå®ããå Žåã¯ç¬¬ïŒã第ïŒã®åŒæ°ãæŽæ°ã§ãªããã°ãªããŸããã
ãªã®ã§pow()颿°ã¯å®ã¯ä»¥äžã®ãããªãã®ã§ãã2
def pow(a, b, c=None):
result = a ** b
if c is not None:
result = result % c # %ã¯ããŸããæ±ããæŒç®å
return result
1.3. ãŸãšã
**ãšpow()ã¯æŒç®åãšé¢æ°ãšããéãããããŸãã
ãŸããpow()ã¯ç¬¬3åŒæ°ãæå®ããããšãã§ããæå®ããæŽæ°ã§å²ã£ãããŸããæ±ããããšãã§ããŸãã
ãã®ãããªéãããããŸãããåºæ¬çã«ã¯ã©ã¡ãã䜿ã£ãŠæžããŠãè¯ãã§ãã
äŸãã° ã3ã®ïŒä¹ãïŒã§å²ã£ãããŸããã¯ä»¥äžã®ããã«æ§ã
ãªæžãæ¹ãã§ããŸãã
# 以äžã®ãã®ã¯å
šãŠæ£ããçã(=1)ãåŸããã
3 ** 4 % 5
pow(3, 4) % 5
pow(3, 4, 5)
ãã ããïŒçªç®ã®ããã«ãããã颿°ãšæŒç®åãæ··ããå¿ èŠã¯ãªãã®ã§ïŒçªç®ãïŒçªç®ã®ããã«æžããšããã§ãããã
2. éåºŠã®æ¯èŒ
ãã®ç« ã§ã¯**ãšpow()ã®å®è¡éåºŠãæ¯èŒããŸãã
2.1. èšæž¬æ¹æ³
æ£æŽæ° $x, n, m$ ã«ã€ããŠ
x ** npow(x, n)x ** n % mpow(x, n, m)
ã®4çš®é¡ãèšç®ããŸããã
å®è¡æéã®èšæž¬ã«ã¯AtCoderã®ã³ãŒããã¹ã Python(3.8.2)ã䜿çšããåèšç®æ³ã«ã€ããŠïŒåã®èšæž¬ã®å¹³åããšããŸããã
èšæž¬ã«äœ¿çšããã³ãŒãã¯ä»¥äžã®ãã®ã§ãã
def main():
x = 3
n = 10
m = 17
loop = 10000000
for _ in range(loop):
result = x ** n
#result = pow(x, n)
#result = x ** n % m
#result = pow(x, n, m)
#pass
if __name__ == "__main__":
main()
2.2. èšæž¬çµæ
çµæã¯ä»¥äžã®ããã«ãªããŸããã
$x=3, m = 17$ ã¯åºå®ã§ n ãš loop ãå€ãèšæž¬ããŸããã
ãªãã$loop = 10^7$ ã§foræå
ãpassã®å Žåã¯$196\rm{ms}$ ã§ããã
ïŒiïŒããŸãããšããªãå Žå
| n | loop | x ** n |
pow(x, n) |
|
|---|---|---|---|---|
| $10$ | $1$ | $21\rm{ms}$ | $22\rm{ms}$ | |
| $10$ | $10^7$ | $1885\rm{ms}$ | $2163\rm{ms}$ | |
| $10^7$ | $1$ | $2526\rm{ms}$ | $2516\rm{ms}$ | |
| $10^3$ | $2 \times10^6$ | $2311\rm{ms}$ | $2436\rm{ms}$ |
ïŒiiïŒããŸãããšãå Žå
| n | loop | x ** n % m |
pow(x, n, m) |
|
|---|---|---|---|---|
| $10$ | $1$ | $22\rm{ms}$ | $22\rm{ms}$ | |
| $10$ | $10^7$ | $2074\rm{ms}$ | $6319\rm{ms}$ | |
| $10^7$ | $1$ | $2553\rm{ms}$ | $25\rm{ms}$ | |
| $10^3$ | $2 \times10^6$ | $3652\rm{ms}$ | $1430\rm{ms}$ |
2.3. ãŸãšã
çµæããŸãšãããšäžå³ã®ããã«ãªããŸãã
é床ãéèŠãããå Žåã«æšå¥šããæ¹æ³ã瀺ããŸãã
空çœéšåã¯ã©ã¡ãã§ã倧ããªéãã¯ãããŸããã
åœç¶ã§ãããã¹ãä¹èšç®ã«ã©ã¡ãã®æ¹æ³ã䜿ããèãããããã¢ã«ãŽãªãºã èªäœãæŽç·Žãããããšã«æéã䜿ã£ãæ¹ãè¯ãã§ããã¹ãä¹èšç®ã®éããéèŠã«ãªã£ãŠããå Žé¢ã¯ç¹å®ã®å Žé¢(nã倧ãã & ããŸãããšã)ãé€ããŠã»ãšãã©ãªãã§ãããã
ãªã®ã§ãã®çµæã¯ãªããã¡ãã£ãšéãããããªçšåºŠã«ãšã©ããŠãå®éã¯ã³ãŒãã®çµ±äžæ§ãªã©ã§æ±ºããæ¹ããããšæããŸãã
- n(æ£ç¢ºã«ã¯$x^n$)ã倧ãã & ããŸãããšã $\rightarrow$
pow()ã䜿ã - ãã®ä»ã$\rightarrow$ ã³ãŒãã®çµ±äžæ§ãªã©ã§æ±ºãã
3. Pythonå éšã®ã¯ãªã
ç«¶æããã°ã©ãã³ã°ãå§ããŠéããªãé ãã¹ãä¹èšç®ã«ã€ããŠèª¿ã¹ãŠã¿ããšæ¬¡ã®ãããªæèšãããç®ã«ããŸããã
Pythonã®çµã¿èŸŒã¿é¢æ°pow()ã¯ç¹°ãè¿ãäºä¹æ³ãçšããŠå®è£
ãããŠãã
åœæã¯ããµãŒããããªãã ã䟿å©ã ãªããšããæããªãã£ãã®ã§ãããããã確ãããããšã¯ãªããªãšæã調ã¹ãŠã¿ãã®ããã®èšäºãæžãããã£ããã§ãã
ãã®ç« ã§ã¯å®éã«Pythonã®ãœãŒã¹ã³ãŒããã¿ãŠ**ãšpow()ã®éãã«ã€ããŠèª¿ã¹ãçµæã説æããŸãã
ãªããåºãææ°ã¯æŽæ°ã®ã¿ãæ³å®ããŸãã
åèã«ãããœãŒã¹ã³ãŒã
ãªãªãžãã«ã®ãCèšèªã§å®è£
ãããããããCPythonã§ãããŒãžã§ã³ã¯3.8ã§ãã以äžã®ãªã³ã¯ããã¿ãããšãã§ããŸãã
https://github.com/python/cpython/tree/3.8
3.1. 調ã¹ãæ¹æ³
Pythonæšæºã®disã¢ãžã¥ãŒã«ã䜿ããŸãããã®ã¢ãžã¥ãŒã«ã䜿ãããšã§ãã³ãŒããå®è¡ããéã«å
éšã§è¡ãããŠããåŠçã人éãããã圢ã§ã¿ãããšãã§ããŸãã
äŸãã°ã以äžã®ãããªã³ãŒããæžããŸãã
x = 1
y = 2
x + y
ãããŠ
$ python -m dis test.py
ãšå®è¡ãããš
1 0 LOAD_CONST 0 (1)
2 STORE_NAME 0 (x)
2 4 LOAD_CONST 1 (2)
6 STORE_NAME 1 (y)
3 8 LOAD_NAME 0 (x)
10 LOAD_NAME 1 (y)
12 BINARY_ADD
14 POP_TOP
16 LOAD_CONST 2 (None)
18 RETURN_VALUE
ãã®ãããªçµæã衚瀺ããããšæããŸãã
ãããããBINARY_ADDãšããã®ãè¶³ãç®ãããŠããããã ãšããããšãããããŸãã
ããšã¯ãœãŒã¹ã³ãŒãããBINARY_ADDã®å®çŸ©ãæ¢ããŠè¿œã£ãŠããã°å
éšã§ã®åŠçãããããŸãã
3.2. ïŒïŒã®å Žå
以äžã®ã³ãŒãã䜿ã£ãŠèª¿ã¹ãŸããã
x = 3
y = 4
x ** y
ãããšä»¥äžã®ããã«ãªããŸãã
1 0 LOAD_CONST 0 (3)
2 STORE_NAME 0 (x)
2 4 LOAD_CONST 1 (4)
6 STORE_NAME 1 (y)
3 8 LOAD_NAME 0 (x)
10 LOAD_NAME 1 (y)
12 BINARY_POWER
14 POP_TOP
16 LOAD_CONST 2 (None)
18 RETURN_VALUE
ãã£ãŠBINARY_POWERãšãããã®ãæ¢ããŸãã
ããã远ã£ãŠãããšæ¬¡ã®ããã«ãªããŸãã
BINARY_POWER $\rightarrow$ PyNumber_Power $\rightarrow$ ternary_op $\rightarrow$ long_pow
3.3. pow()ã®å Žå
以äžã®ã³ãŒãã䜿ã£ãŠèª¿ã¹ãŸããã
x = 3
y = 4
pow(x, y)
ãããšä»¥äžã®ããã«ãªããŸãã
1 0 LOAD_CONST 0 (3)
2 STORE_NAME 0 (x)
2 4 LOAD_CONST 1 (4)
6 STORE_NAME 1 (y)
3 8 LOAD_NAME 2 (pow)
10 LOAD_NAME 0 (x)
12 LOAD_NAME 1 (y)
14 CALL_FUNCTION 2
16 POP_TOP
18 LOAD_CONST 2 (None)
20 RETURN_VALUE
pow()ã®å Žåã¯BINARY_POWERã§ã¯ãªãCALL_FUNCTIONãšãªããŸãã
ããã¯ãçµã¿èŸŒã¿é¢æ°ã ãã§ãªãã³ãŒãäžã«èªåã§æžãã颿°ãªã©ãå
šãŠã®é¢æ°ãCALL_FUNCTIONã«ãªããŸãã
CALL_FUNCTIONãããœãŒã¹ã³ãŒãã远ã£ãŠã¿ããšæ¬¡ã®ããã«ãªããŸãã
CALL_FUNCTION $\rightarrow$ call_function $\rightarrow$ _PyObject_Vectorcall
ãããŠ_PyObject_Vectorcallã®ãªãã§ä»¥äžã®ããšãè¡ãããŸãã
\begin{aligned}
\rm{func} &= \rm{\_PyVectorcall\_Function}\\
&= \rm{builtin\_pow\_impl}\\
&= \rm{PyNumber\_Power}\\
&= \rm{ternary\_op}\\
&= \rm{\mathbf{long\_pow}}\\
\rm{result} &= \rm{func}()\\
&\rm{\_Py\_CheckFunctionResult}
\end{aligned}
3.4. long_pow
å®ã¯ã©ã¡ãã®æ¹æ³ã§ã¹ãä¹èšç®ãããããšããŠãçµå±long_powãšãã颿°ã«ãã©ãçããŸãã
long_powãPythonã§æžããŠã¿ããšã ããã以äžã®ããã«ãªããŸãã(åç §ã«ãŠã³ããæ¡ã倧ããå Žåã®åŠçãªã©ã¯çç¥ããŠããŸãã)
def long_pow(base, exp, mod): #base, exp, modã¯int
negativeOutput = 0
# ææ°ãè² ã§modããªãå Žåã¯floatã®çޝä¹ãžç§»ã
if exp < 0 and mod is None:
return float_pow(base, exp, mod)
# modãæå®ãããŠããå Žåã®åŠç
if mod != None:
#mod = 0ã¯ãšã©ãŒ
if mod == 0:
raise ValueError
#modãè² ãªãnegativeOutputãã©ã°ãç«ãŠãŠmodãæ£ã«ãã
if mod < 0:
negativeOutput = 1
mod = -mod
# mod = 1ãªãå¿
ã0
if mod == 1:
return 0
# ææ°ãè² ãªãææ°ãæ£ã«ããŠåºãmodãæ³ãšããéå
ã§çœ®ãæãã
if exp < 0:
exp = -exp
base = long_invmod(base, mod)
# åºãè² ãããã¯modãã倧ãããªãmodã§å²ã£ãäœãã«çœ®ãæãã
if base < 0 or base > mod:
_, base = divmod(base, mod)
"""
ãããŸã§ã§modãæå®ãããŠããå Žåã¯base, exp, modãéè² ã«ãªãã
modãæå®ãããŠããªãå Žåã¯baseãè² ã®å Žåãããã
"""
# modãæå®ãããŠããå Žåãxãmodã§å²ã£ãäœãã«çœ®ãæãã
def REDUCE(x):
if mod != None:
_, x = divmod(x, mod)
return x
# xãšyã®æãç®ãmodãæå®ãããŠããå Žåã¯ããŸãããšã
def MULT(x, y):
result = x * y
result = REDUCE(result)
return result
# å³åããã€ããªæ³ïŒç¹°ãè¿ãäºä¹æ³ïŒ
j = 1 << exp.bit_length() - 1
z = 1
while j:
z = MULT(z, z)
if exp & j:
z = MULT(z, base)
j >>= 1
# negativeOutputã®å Žåã¯çµæãè² ã«ãã
if negativeOutput and z != 0:
z -= mod
return z
以äžãããPythonã®çµã¿èŸŒã¿é¢æ°pow()ã¯ç¹°ãè¿ãäºä¹æ³ãçšããŠå®è£
ãããŠããããšããæèšã¯æ£ããã§ãã誀解ãå«ãã§ãããšæããŸããïŒç§ãåæã«èª€è§£ããŠããã ããããããŸãããïŒ
æ£ãã
確ãã«çµã¿èŸŒã¿é¢æ°pow()ã¯ç¹°ãè¿ãäºä¹æ³ãçšããŠå®è£
ãããŠããŸãã
誀解(ïŒ)
pow() ""ã¯"" ç¹°ãè¿ãäºä¹æ³ã~ãšããããšã¯**ã¯éã?
$\rightarrow$ **ãç¹°ãè¿ãäºä¹æ³ãçšããŠå®è£
ãããŠããŸãã
ãããããã©ã¡ããåã颿°ã䜿ã£ãŠããŸãã
以éã§ã¯ããããŸã§ã§ããã£ãããšãåºã«ïŒç« ã®çµæã説æããŸãã
3.5. ããŸãããšããªãå Žå
ãŸããããŸãããšããªãå ŽåãèŠãŠãããŸãã
ãã®å Žåã©ã¡ããlong_pow(x, n, None)ãå®è¡ãããã ããªã®ã§
x ** npow(x, n)
ã¯ã¢ã«ãŽãªãºã ã®é¢ã§ã¯å®å šã«çããã§ãããããã£ãŠã$n$ ãã©ã®ãããªå€§ããã§ãã£ãŠãïŒã€ã«éãã¯ãããŸããã
ïŒç« ã§è¿°ã¹ãéãã**ã¯æŒç®åãpow()ã¯é¢æ°ã§ããããã§ã¯ãã®éããéèŠã«ãªããŸãã
ããã§3.2, 3.3ã§ããã£ãPythonå éšã®åãããŸãšããŠã¿ããšäžå³ã®ããã«ãªããŸãã
ãã®å³ãããããããã«ã颿°ãåŒã³åºãéã«ã¯ã³ã¹ã(颿°åŒã³åºãã®ãªãŒããŒããã)ãæ¯æãããšã«ãªããŸãã
ïŒåã®åŒã³åºãã§ã¯äœæã§ããå·®ã¯çãŸããŸããããåŒã³åºãåæ°ãå¢ããã°å€§ããªå·®ã«ãªããŸãã
ãã®ãããªçç±ããã
- n ã®å€§ããã«äŸåããªã
- loopã倧ãããªãã»ã©æŒç®åã§ãã
**ã颿°ã§ããpow()ããé床é¢ã§åªäœã«ãªã
ãšãã2ç« ã®çµæã説æã§ããŸãã
3.6. ããŸãããšãå Žå
ç¶ããŠãããŸãããšãå ŽåãèŠãŠãããŸãã
ãã®å ŽåãæŒç®åãšé¢æ°ã®éãããloopã®å€§ããã«ãã£ãŠæŒç®åã®åªäœæ§ãèŠããŠããŸãã
äžæ¹ãããŸãããšããªãå Žåãšéãã®ã¯ã¢ã«ãŽãªãºã ã®é¢ã§ãïŒã€ã¯ç°ãªããšããéšåã§ãã
x ** n % mã§ã¯ããŸããæ±ããã®ã¯æåŸã ããªã®ã«å¯Ÿããpow(x, n, m)ã¯ä¹ç®ããšã«ããŸããæ±ããŸããããããã¯ãããã®éãã n ã®å€§ããã«ãã£ãŠã©ã®ããã«åœ±é¿ããããèŠãŠãããŸãã
n ãå°ããå Žå
ãã®å Žåããå²ãç®ã®ã³ã¹ãã¯å°ãããªãããšããäºå®ãéèŠã«ãªã£ãŠããŸããããŸããæ±ãããšããã®ã¯å²ãç®ãããããšã«ä»ãªããªãã®ã§äœåºŠãããŸããæ±ããpow(x, n, m)ã¯äžåºŠããããŸããæ±ããªãx ** n % mã«æ¯ã¹ãŠèšç®ã³ã¹ãã倧ãããªããŸãã
n ã倧ããå Žå
ãã®å Žåãã倧ããªæ°ã®æãç®ã®ã³ã¹ããç¡èŠã§ããªãããšããäºå®ãéèŠã«ãªããŸãã$x^n$ ã¯ææ°é¢æ°ã§ãã®ã§ n ã倧ãããªããš $x^n$ ã¯éåžžã«å€§ãããªããŸãããã®ãããäžæçã« $x^n$ ãã®ãã®ãæ±ããx ** n % mã¯åžžã« m æªæºã®æ°ã®æãç®ãããpow(x, n, m)ã«æ¯ã¹ãŠèšç®ã³ã¹ãã倧ãããªããŸãã
ãããããŸãšãããš
- n ãå°ãã loop ã倧ããå Žåã¯å²ãç®ãšé¢æ°åŒã³åºãã®ã³ã¹ããæ¯é
çã«ãªã
pow()ã®æ¹ã**ããé ããªã - n ã倧ãã loop ãå°ããå Žåã¯å€§ããªæ°ã®æãç®ã®ã³ã¹ããæ¯é
çã«ãªã
**ã®æ¹ãpow()ããé ããªã - n ãš loop ãå
±ã«å€§ããå Žåã¯ãããã®ãããåãã«ãªããã$x^n$ ãææ°é¢æ°ã ãšããããšããµãŸãããšæŠã
**ã®æ¹ãpow()ããé ããªã
ãšããããã«ïŒç« ã®çµæã説æã§ããŸãã
3.7. ãŸãšã
**ãšpow()ã¯å
±ã«long_powãšãã颿°ã«ã€ãªãã£ãŠããŠãlong_powã¯ç¹°ãè¿ãäºä¹æ³ãçšããŠå®è£
ãããŠããŸãã
**ãšpow()ã®å®è¡éåºŠãæ¯èŒãããã€ã³ãã¯
- ããŸãããšããªãå Žåã¯ã颿°åŒã³åºãã®ãªãŒããŒãããã
- ããŸãããšãå Žåã¯å ããŠãå²ãç®ããšã倧ããªæ°ã®æãç®ã
ã§ãããã®ã³ã¹ãã®ãã¡ã©ããæ¯é çã«ãªãããèããããšã«ãã£ãŠå€æã§ããŸãã
4. ãããã«
å®çšæ§ã¯ããŸããªããããªå 容ã§ãããPythonã«ã€ããŠçè§£ãæ·±ãŸã£ãã®ã§ããã£ãã§ãã
説æã®ééãããã°çãããŸããããç¥ãããã ããã
-
ä»ã«ãmath.pow()ãnumpy.power()ãªã©æ§ã ãªæ¹æ³ããããŸããæ¬èšäºã§ã¯importãªãã§æ±ããïŒã€ã®æ¹æ³ã®ã¿ãæ±ããŸãã â©
-
å®éã«ã¯pow(a, b, c)ãš a ** b % cã¯å éšã§ã®èšç®ã®ä»çµã¿ãç°ãªããŸããa,bãïŒæ¡çšåºŠã®å°ããªæ°ãªãã°æ°ã«ããªããŠããã§ããæ°ã«ãªãæ¹ã¯ïŒç« ãèŠãŠãã ããã â©

