2
0

More than 1 year has passed since last update.

pythonでフロア関数を利用する場合は`//`演算子を使った方が良さそうであるという話(math.floorではなく)

Last updated at Posted at 2022-02-19

pythonでフロア関数を利用する場合はmath.floorもしくは//演算子を使う方法がある

使ってみた

test.py
import math
x = 12345

print("---")
print(x)
print("---")
print(math.floor(x/10))
print(x//10)

y = 2**56

print("---")
print(y)
print("---")
print(math.floor(y/10))
print(y//10)

小さな数値の場合は結果が一致するが、大きな数値の場合は実行すると微妙に結果が違う

$ python test.py
---
12345
---
1234
1234
---
72057594037927936
---
7205759403792794
7205759403792793

math.floorの仕様をみるとPython の浮動小数点型は 53 ビット以上の精度をもたないという事で、16桁を超えるような数値を扱う場合は誤差が出ると思われる。

※コメント指摘により修正しました。誤解を招く表現ですみません。
Python の浮動小数点型は 53 ビット以上の精度をもたないという事で、math.floorの実行前に16桁を超えるような数値を割り算すると誤差が出て思ったような結果にならない事が起こる。
フロア関数を利用する場合は//演算子を使った方が良さそうである。

https://docs.python.org/ja/3/library/math.html#math.trunc
ceil() 、 floor() 、および modf() 関数については、非常に大きな浮動小数点数が 全て 整数そのものになるということに注意してください。通常、Python の浮動小数点型は 53 ビット以上の精度をもたない (プラットフォームにおける C double 型と同じ) ので、結果的に abs(x) >= 2**52 であるような浮動小数点型 x は小数部分を持たなくなるのです。

文字列を操作する場合

def myfloor(STR):
    ans = 0
    if 0 <= int(STR) < 10:
        # 1桁の正の数                                                                                                                                                                                    
        ans = 0
    elif -10 < int(STR) < 0:
        # 1桁の負の数                                                                                                                                                                                    
        ans = -1
    elif int(STR) > 0:
        # 2桁以上の正の数                                                                                                                                                                                
        ans = int(STR[:len(STR)-1])
    elif STR[-1] != '0':
        # (最後の桁が0以外の)2桁以上の負の数、floor関数を使った時に-1する必要がある                                                                                                                      
        ans = int(STR[:len(STR)-1])-1
    else:
        # (最後の桁が0の)2桁以上の負の数、floor関数を使った時に-1する必要がない                                                                                                                          
        ans = int(STR[:len(STR)-1])
    return ans

print(myfloor(50))        #5
print(myfloor(234567))    #23456
print(myfloor(-234567))   #-23457
print(myfloor(-(2**56)))  #-7205759403792794

参考

2
0
2

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
2
0