Pythonの罠
list
のコピー
a = [1,2,3]
b = a
b[0] = 0
print(a)
[0,2,3]
なんと,b
の代入元であるa
も変わってしまった.
これを回避するために,a
のcopy
を作る必要がある.
a = [1,2,3]
b = a.copy()
b[0] = 0
print(a)
[1,2,3]
割り算の演算子
a = 5
b = 2
print(a/b)
print(a//b)
2.5
2
/
は小数点以下を含む割り算を行う.//
は小数点以下を切り捨てた割り算を行う.
/
を大きな整数で使おうとすると正しい結果が得られない.
次のプログラムでは,$9999\cdots9999$を$3$で割った値,すなわち$3333\cdots3333$を求めたい.
a = 999999999999999999999999999999999999999999999999999999999999999999999999999999999999
b = 3
print(a/b)
print('{:.1000g}'.format(a/b)) #eを使わない表示にする.
print(a//b)
3.333333333333333e+83
333333333333333316642274409837779174589735593005847147516488057690807469867494539264
333333333333333333333333333333333333333333333333333333333333333333333333333333333333
演算子/
を使った場合,でたらめな値が得られたことがわかる.
//
を使うと,正しい値が得られる.
小数を扱う関数
sqrt
関数,pow
関数などは小数で計算をする.
a = 10
b = pow(a,100)
print('{:.10000g}'.format(b))
x = 10000000000000000000000000000000000
a = x*x
b = sqrt(a)
print('{:.10000g}'.format(b))
10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104
9999999999999999455752309870428160
わけのわからない値が得られる. 基本的に標準ライブラリの関数は信用してはいけない.PyCryptodome,sagemath,NumPyなどのライブラリを使うか,自分で実装する必要がある.
再帰関数の深さ
def f(n):
if n==0:
return 0
return f(n-1)+1
print(f(100000))
RecursionError: maximum recursion depth exceeded in comparison
再帰関数の深さ(recursion depth)の最大値は,デフォルトでは$1000$である.
これを変更するには,sys
モジュールを使う.
import sys
sys.setrecursionlimit(1000000)