DynamoDBにNumber
型で数値データを登録して、計算しようと思うと次のようなエラーが出た
error
unsupported operand type(s) for *: 'decimal.Decimal' and 'float'
どうやら、DynamoDBのNumber
型はDecimal
型らしい。
int
やfloat
を使うことで、それぞれの型に変換できる。
実験
ところで、この記事によれば、decimal型はfloat型に比べて処理が重いらしい。
実行時間はAWSの料金を決定する非常に重要なファクターだ。
そこで、以下のようなプログラムを作成して実験してみた。
実験の内容は以下の通り
- floatのみで計算
- decimalのみで計算
- decimalをfloatにして計算
- decimalをstrに変換し、それをfloatにして変換1
test-decimal.py
import time
from decimal import *
import numpy as np
import matplotlib.pyplot as plt
def getAverageTime(N:int):
print("do "+str(N)+" times")
ary1=np.array([])
#froatのみ
for i in range(N):
start=time.time()
result=float(1)/float(3)*float(10)/float(3)
elapsed_time = time.time() - start
ary1=np.append(ary1,float(elapsed_time))
#decimalのみ
ary2=np.array([])
for i in range(N):
start=time.time()
result=Decimal("1")/Decimal("3")*Decimal("10")/Decimal("3")
elapsed_time = time.time() - start
ary2=np.append(ary2,float(elapsed_time))
#decimal→float
ary3=np.array([])
for i in range(N):
start=time.time()
result=float(Decimal("1"))/float(Decimal("3"))*float(Decimal("10"))/float(Decimal("3"))
ary3=np.append(ary3,float(elapsed_time))
#decimal→str→float
ary4=np.array([])
for i in range(N):
start=time.time()
result=float(str(Decimal("1")))/float(str(Decimal("3")))*float(str(Decimal("10")))/float(str(Decimal("3")))
elapsed_time = time.time() - start
ary4=np.append(ary4,float(elapsed_time))
print ("average time of float: {0}".format(np.average(ary1)) + "[sec]")
print ("average time of decimal: {0}".format(np.average(ary2)) + "[sec]")
print ("average time of decimal to float: {0}".format(np.average(ary3)) + "[sec]")
print ("average time of decimal to float with str: {0}".format(np.average(ary4)) + "[sec]")
label=["float","decimal","decimal to float", "decimal to float \nwith str"]
left=np.array([1,2,3,4])
height=np.array([np.average(ary1),np.average(ary2),np.average(ary3),np.average(ary4)])
plt.bar(left,height,tick_label=label,align="center")
plt.title("do "+str(N)+" times")
print("\n")
plt.savefig('figure' + str(N)+'.png')
plt.clf()
if __name__=="__main__":
getAverageTime(1)
getAverageTime(3)
getAverageTime(100)
getAverageTime(1000)
結果
以下の結果が得られた
考察
いずれの実行方法でも、floatは最も早く計算が終了している。
1回のみ実行した場合はdecimal型をfloat型に変換をしてもしなくても実行時間に変化はない。
一方、実行回数が多い場合はdecimal型からfloat型にすることで、計算時間を大幅に短縮することができた。
decimalからstrを介してfloatに変換することで、値の正確性は保てるものの計算時間はどの実行方法よりも多いことがわかった。