LoginSignup
26
23

More than 3 years have passed since last update.

Python 小数点以下の任意桁で切り捨て

Last updated at Posted at 2019-07-20

概要

  • Pythonで小数点以下の任意の桁で切り捨てをする時に少しハマったのでやり方をまとめます。

桁数が小さい場合

import math

n = 2  # 切り捨てしたい桁
x = 1.555
y = math.floor(x * 10 ** n) / (10 ** n)
print(x, "=>", y)  # 1.555 => 1.55

考え方としては、切り捨てたい桁数の数字が整数になるまで10^nをかけて、そこでmath.floorを使う。その後、10^nで割って小数に戻す。標準ライブラリのmath.floorが小数点以下を全て切り捨てとなるため。
例で言ったら、1.555155.5にして切り捨て。その後、1.55に戻している。

桁数が大きい場合

from decimal import *

root2 = Decimal(2) ** Decimal(0.5)
n = 18  # 小数第18位
y = Decimal(str(root2)).quantize(Decimal(str(10**(n*-1))), rounding=ROUND_DOWN)
print(root2, "=>", y)  
# 1.414213562373095048801688724 => 1.414213562373095048

ハマったのはこっち。有効桁数が大きい(18桁くらい?)になるとどうしても誤差が入る。decimalのROUND_DOWNを使うと高い精度で切り捨てできる。

DecimalのROUND_DOWNを使わない場合
n = 18  # 切り捨てしたい桁
x = 2 ** 0.5
y = math.floor(x * 10 ** n) / (10 ** n)
print(Decimal(x), "=>", y)
# 1.4142135623730951454746218587388284504413604736328125 
#  => 1.4142135623730951 ※切り捨て前の値で誤差が出ている

(2019/7/21: コメントいただいて修正しました。ありがとうございます)

Decimalで文字列として設定すれば桁数の大きい値も保持できる。

>>> Decimal('123456.1234567890123')
Decimal('123456.1234567890123')

ただ、Decimalではない変数に入れた時点で誤差含みになる。この例だと、小数第11位からずれる。解決策は無さそう。

>>> d = {"value": 123456.1234567890123}
>>> Decimal(d["value"])
Decimal('123456.1234567890060134232044219970703125')
>>> Decimal(str(d["value"]))
Decimal('123456.123456789')
# 文字列で設定すると15桁の有効数字で表示

参考

26
23
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
26
23