1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DynamoDBで数値データを扱う際の処理と、decimal型とfloat型の実行時間の比較

Posted at

DynamoDBにNumber型で数値データを登録して、計算しようと思うと次のようなエラーが出た

error
unsupported operand type(s) for *: 'decimal.Decimal' and 'float'

どうやら、DynamoDBのNumber型はDecimal型らしい。

intfloatを使うことで、それぞれの型に変換できる。

実験

ところで、この記事によれば、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)

結果

以下の結果が得られた

  • 1回実行時
    figure1.png

  • 3回実行時
    figure3.png

  • 100回実行時
    figure100.png

  • 10000回実行時
    figure1000.png

考察

いずれの実行方法でも、floatは最も早く計算が終了している。
1回のみ実行した場合はdecimal型をfloat型に変換をしてもしなくても実行時間に変化はない。
一方、実行回数が多い場合はdecimal型からfloat型にすることで、計算時間を大幅に短縮することができた。
decimalからstrを介してfloatに変換することで、値の正確性は保てるものの計算時間はどの実行方法よりも多いことがわかった。

  1. このサイトで紹介されている手法で、decimalの持つ値の正確性を保ちつつ、floatに変換することができる手法

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?