【Python】小数点の切り捨てをわかりやすく解説

はじめに

Pythonで浮動小数点の値を扱うとき、小数点以下を切り捨てたいという場面があるのではないでしょうか。金額の調整やデータ分析時の表示など、さまざまな実務のシーンで小数点の処理方法が問題になることがあります。

しかし、切り捨てと聞くと簡単そうに思えますが、Pythonには複数のやり方があり、それぞれ挙動が異なることもあるのです。たとえば、int()math.floor()math.trunc()Decimalといった方法があり、負の数に対してどう振る舞うかも少しずつ異なります。

この記事では、Pythonにおける小数点の切り捨て方法を丁寧に整理し、初心者の方でも理解しやすいようにサンプルコードを交えながら解説します。実際のビジネスや開発現場での活用例や、注意すべきポイントについてもあわせて紹介していきます。小数点の扱いで悩むことが減り、Pythonでの開発がよりスムーズになることを目指します。

ここから段階的に説明していきますので、初心者の方は一歩ずつ順を追って学んでみてください。きっと、自分の用途に最適な小数点切り捨ての方法が見つかるはずです。

この記事を読むとわかること

  • Pythonにおける小数点の扱いの基本
  • 切り捨てと丸めの違いの理解
  • int()math.floor()math.trunc()Decimalそれぞれの使い方
  • 小数点以下の桁数を指定した切り捨て方法
  • 金融やデータ分析など実務での活用シーン
  • 負の数や浮動小数点特有の注意点
  • パフォーマンスや使い分けの考え方

Pythonにおける小数点の扱いとは

Pythonでは、浮動小数点数を扱うときにいくつかの特徴があります。整数型とは違い、内部で2進数の形式を用いて数値を表現するため、どうしても誤差が生じる場合があるのです。例えば、0.1 + 0.2は、理想的には0.3ですが、実際にはごくわずかに異なる値になることがよく知られています。

この背景として、プログラミングにおいては10進数ではなく2進数で計算が行われるからという理由が挙げられます。したがって、単純に小数点以下を切り捨てたいと思ったときでも、計算結果にわずかな誤差が存在すると、意図せぬ結果になってしまうかもしれません。

小数点を切り捨てる方法を理解するためには、まずこうした浮動小数点の内部的な表現や、Pythonが持つさまざまな数値型の特徴を押さえておくと役立ちます。単純に「小数点以下を消す」という操作でも、どの方法を選ぶかで結果が異なることもあるので注意が必要です。

浮動小数点数の基本

Pythonの標準的な浮動小数点型は、いわゆる「ダブルプリシジョン(倍精度浮動小数点数)」です。これはコンピュータのハードウェアと親和性が高く、高速に計算できるというメリットを持ちます。

一方で、先述したように「0.1」や「0.2」といった10進数が、2進数では正確に表現できないケースが存在します。そのため、計算をすればするほど誤差が蓄積していく場合があるのです。小数点を扱う上で、この浮動小数点の誤差は常に考慮しなければならないポイントと言えるでしょう。

切り捨てと丸め、混同しやすい2つの処理

小数点を「切り捨てる」という動作は、「丸める」と混同されがちです。切り捨ては単に小数点以下を捨てる動作ですが、丸めには「四捨五入」「切り上げ」「銀行丸め」など複数の手法があります。

Pythonのround()関数は四捨五入を行うための関数です。一方で切り捨てはまた別の関数・方法を使います。こうした違いをはっきり区別しておかないと、本来は「1.2」を切り捨てて「1」にしたかったのに「2」になってしまう、といった誤作動を起こしてしまう可能性があります。

「丸め」と「切り捨て」はよく混同されますが、処理の結果が変わるため必ず使い分けを意識しましょう。

小数点切り捨てを行う主な方法

Pythonではいくつかの標準機能を使うことで、小数点以下を切り捨てることができます。代表的なのは、以下の4つです。

  1. int()関数
  2. math.floor()関数
  3. math.trunc()関数
  4. Decimalクラス

ここではそれぞれの方法をサンプルコードとともに解説します。初心者の方は、一つひとつの関数やクラスがどのような挙動をするのか、サンプルを実行しながら学んでみると理解が深まるでしょう。

int()関数で整数化する方法

もっともシンプルな方法として思い浮かぶのが、int()関数を用いて浮動小数点数を整数に変換する方法です。int()関数に浮動小数点数を渡すと、小数点以下が切り捨てられます。以下は簡単な例です。

value1 = 3.7
value2 = 5.9999
value3 = -2.3

print(int(value1))  # 3
print(int(value2))  # 5
print(int(value3))  # -2

小数点以下が取り除かれて整数になります。正の値であれば「切り捨て」ですが、負の値では絶対値が大きくなる方向には動きません。つまり-2.3-2になり、これは「小数点以下が除去された」という感覚に近いでしょう。

ただし、負の数でも小数点以下を削除しているだけで、いわゆる「切り上げ」にはならないという点を意識してください。この挙動は、あくまで「整数部分のみを取り出す」という動作と考えると理解しやすいはずです。

math.floor()関数で切り捨てを行う方法

もう少し「切り捨て」のイメージに近い関数として、多くの方が利用するのがmath.floor()です。math.floor(x)は「xより大きくない最大の整数」を返すので、正の数に対してはint(x)と同じ結果を返します。

import math

value1 = 3.7
value2 = 5.9999
value3 = -2.3

print(math.floor(value1))  # 3
print(math.floor(value2))  # 5
print(math.floor(value3))  # -3

ここで注目すべきは、-2.3を処理した結果が-3になっていることです。負の数の場合、小数点以下の部分があると、より小さい整数に「切り捨て」られます。これは負の数を扱う場合によく混乱するポイントなので、実際のコードで試してみると納得しやすいでしょう。

math.trunc()関数で小数点を切り捨てる方法

math.trunc()関数も小数点以下を切り捨てる機能を持ちますが、負の数の扱いがfloor()とは異なるのが特徴です。trunc()は実質的に整数部分を返す動作を行うので、int()と同じ結果を返します。

import math

value1 = 3.7
value2 = 5.9999
value3 = -2.3

print(math.trunc(value1))  # 3
print(math.trunc(value2))  # 5
print(math.trunc(value3))  # -2

つまり、trunc()はプラス方向への切り上げでもマイナス方向への切り下げでもなく、「単純に小数点部分を削る」というイメージです。負の数は「-2」で止まるので、一般に「切り捨て」と表現されるfloor()とは違う結果を生む可能性があります。

負の数で明確な切り捨てをしたい場合にint()trunc()を使うと、想定と異なる数値になることがあります。実務では特に注意しましょう。

Decimalクラスでの切り捨て方法

浮動小数点の誤差を抑えたい場面では、decimalモジュールのDecimalクラスを活用する方法があります。Decimalは10進数のまま計算を行うので、金融系のアプリケーションなどで特に有用です。

切り捨てを行う場合は、Decimalオブジェクトに対して「丸めのモード」を指定してから演算することが多いです。以下は一つの例です。

from decimal import Decimal, ROUND_FLOOR, ROUND_DOWN

# ROUND_DOWNは小数点以下を単に切り落とす、負の数でも絶対値方向に小さくならない
x = Decimal('-2.3')

print(x.quantize(Decimal('1'), rounding=ROUND_DOWN))  # -2
print(x.quantize(Decimal('1'), rounding=ROUND_FLOOR)) # -3

ROUND_DOWNは正負を問わず小数点以下をただ切り落とす動作で、ROUND_FLOORはその値以下の最も大きい整数(つまり負数の場合はより小さな値)になるよう切り捨てを行います。Decimalモジュールを使うと誤差の面でも制御しやすくなり、また細かい丸めモードを切り替えられる点が利点です。

小数点以下の桁数を指定した切り捨て方法

ここまでは、小数点以下すべてを切り捨てて整数化する方法を紹介してきました。しかし、開発現場では「小数第2位まで表示したい」「小数第3位だけ残して切り捨てたい」といった用途もよくあります。その場合には、次のようなアプローチが考えられます。

文字列フォーマットを活用するケース

小数点以下の桁数を指定したいときに便利なのが、文字列フォーマットを使う方法です。たとえば、format()やf-stringの書式指定を活用すると、任意の桁数で出力ができます。ただし、これはあくまで「表示上の切り捨て」であり、内部的には小数点以下のデータを保持したままになる点に注意してください。

value = 3.14159

# 小数第2位まで表示して、それ以降は切り捨て
formatted_value = f"{value:.2f}"

print(formatted_value)  # 3.14

この例では、Pythonの丸め規則上「3.14」が四捨五入されることがあります。表示用の一時的な出力と、実際の数値計算とで分けて使うと混乱しにくいでしょう。「とにかく出力するときだけ小数点を見えなくしたい」というケースでは有効ですが、ビジネスロジックでの計算としては別の手段を選ぶべき場合が多いです。

数学的計算を使った切り捨て

「小数点第2位まで残して切り捨てたい」など、より直接的に演算でコントロールしたい場合は、以下のように一度スケールをかけてからmath.floor()を使う手法があります。

import math

def truncate_to_nth_decimal(num, n):
    factor = 10 ** n
    return math.floor(num * factor) / factor

print(truncate_to_nth_decimal(3.14159, 2))  # 3.14
print(truncate_to_nth_decimal(-2.347, 2))   # -2.35  (負の数に注意)

正の数では問題なく期待通りに動きますが、負の数は「floor」の働きで思わぬ結果になることがあります。例えば-2.347を小数第2位まで残して切り捨てると、数学的には-2.34のはずですが、floor()はさらに小さい方向へ向かうため、実際には-2.35になっています。

もし常に正の数だけを想定するならこの方法でもよいですが、負の数が混在するならmath.trunc()Decimalモジュールを活用するほうが明確かもしれません。現場で使う前に、必ず負の数や境界値でも挙動を確認しておくと良いでしょう。

実務におけるPythonの小数点切り捨て活用例

ここまでで、小数点を切り捨てるための複数の方法と、それぞれの特徴を見てきました。では、具体的にどのような実務シーンでこれらの手段を使い分けるのでしょうか。以下では代表的なケースを紹介します。

金融計算での金額の切り捨て

金融計算の世界では、小数点以下の円未満を切り捨てたり、業務ルールによっては小数第2位まで扱ったりすることが珍しくありません。このような場合、Decimalモジュールを用いたほうが良いとされることが多いです。理由は、浮動小数点の誤差が許容できないシビアな計算が多いからです。

たとえば、顧客の請求金額や取引履歴の集計で誤差が出ると大きなトラブルにつながる可能性があります。そのため、浮動小数点の誤差が許されない状況ではDecimalの活用が推奨されます。また、小数点以下をどのように扱うか(四捨五入、切り捨て、切り上げなど)は組織や国のルールによってさまざまなので、事前に運用ルールを確認しておく必要があります。

データ分析での小数点トリミング

データ分析では、高精度が求められる場面と、ざっくりした統計値で問題ない場面があります。たとえば、統計レポート用に結果を出力するときは、小数点以下の桁数が多すぎると見づらいため、適度に切り捨てて表示することがあるでしょう。この場合は単純にformat()で見やすい桁数に整形したり、math.trunc()を使って値を一時的にトリミングしたりすることがあります。

ただし、内部的な分析用データとしては精度を保った状態の値を保持しておき、最終的な表示だけを切り捨てにするという使い分けが多いです。誤差が大きくなると分析結果に影響が及ぶので、実データと表示用のデータは別管理にするほうが安全です。

float型の精度誤差による問題

Pythonの浮動小数点型(float)は内部で2進数を用いており、例えば「10.1」などは正確に表現されません。これはPythonに限った問題ではなく、ほぼすべての言語で共通です。

2進数表現に起因する浮動小数点誤差

具体的な例として、0.1 + 0.2 == 0.3を判定しようとすると、Falseになることがあります。これは、「0.1」も「0.2」も2進数で完全に表せないため、内部で微妙なずれが生じ、それらを加算するとごくわずかな誤差が残るからです。

小数点以下を切り捨てる処理を行う際も、この誤差が思わぬ結果を生むことがあります。たとえば3.999999999999999のように誤差が出た結果、意図せず3に近い値になってしまい、int()で処理したら「3」ではなく「2」になった、といったトラブルです。こうした問題を最小化するために、あらかじめ適切な方式(Decimalなど)を選ぶ必要があります。

Decimalで誤差を抑制するメリット

Decimalは10進数をそのまま扱うため、金融計算や予算管理など、誤差が致命的なシーンで大いに役に立ちます。さらに先ほど述べた通り、quantize()メソッドを使えば自由な丸めモードが設定できるので、業務ルールに沿った小数点の扱いが容易です。

ただし、Decimalfloatに比べると計算速度が遅い傾向があるため、パフォーマンス面を考慮したうえで使い分ける必要があるかもしれません。もし大量の数値を高速に処理する場合は、性能を確保するためにfloatを使うという選択肢も出てくるでしょう。

注意点:負の数における挙動の違い

ここまで繰り返し述べてきたように、負の数を切り捨てる際には特別な注意が必要です。floor()は「x以下の最大の整数」なので、-2.3を与えると-3になります。一方、int()math.trunc()は-2を返します。

もし「負の値でも一律に小数点以下を削りたい」というニーズがあるなら、int()trunc()を使うほうが自然です。逆に「常に小さい値方向に丸めたい(税金計算など)」ならfloor()を使うと意図した挙動に近い結果が得られるでしょう。現場ではどちらが正しいかは業務要件次第なので、あらかじめ仕様を確認しておくことが大切です。

パフォーマンスの視点

int()math.trunc()などは比較的高速に処理できますが、Decimalを多用すると計算量が膨大な場合には処理が遅くなる可能性があります。特に大規模なデータセットをリアルタイムで扱うようなプロジェクトでは、レスポンスの速さが求められる場面もあるでしょう。

  • 大量の数値を瞬時に切り捨てる場合はint()math.floor()などの軽量な関数が適していることが多い
  • 誤差が許されない金額処理ではDecimalを選ぶ方が安心だが、性能面とのトレードオフに注意

このように、プロジェクトの要件(精度・速度・負の数の扱い方など)を総合的に見極めて、適切な方法を選ぶことが必要になります。

math.floor()とmath.trunc()の違いのまとめ

ここで改めて、floor()trunc()の違いを簡単に比較してみましょう。

  • math.floor(x)

    • xを「それ以下の最大の整数」にする。
    • 正の数では単なる切り捨てだが、負の数では絶対値が大きくなる方向へ丸められる。
    • 金融計算などで負の値をより小さい方にそろえたい場合に利用されることがある。
  • math.trunc(x)

    • xの小数点以下を削ぎ落として整数部分だけを返す。
    • int()とほぼ同じ挙動をする。
    • 正の数に対してはfloor()と同じになるが、負の数ではfloor(x)より値が大きくなる(-2.3 -> -2)。

両者の違いは負の数で顕著になります。どちらが正しいかはユースケースによりますので、必ず要件を確認しましょう。

まとめ

Pythonで小数点を切り捨てる方法はいくつかあり、**int()math.floor()math.trunc()Decimal**それぞれで負の数や誤差の扱いが異なります。さらに、金融計算など誤差が許されない場面ではDecimalの利用が有効であり、パフォーマンスや要件に応じて最適なアプローチを選ぶことが肝心です。

実務の現場では、小数点を切り捨てる処理が思わぬ結果につながるケースもあります。特に負の数の挙動は混乱が起こりやすい部分なので、必要に応じてテストデータを用意して確認しておくと安心です。表示上だけ小数点を減らしたいのか、あるいは実際の計算結果をそのまま切り捨てたいのかを明確にし、用途に合わせて正しく使い分けてみてください。

Pythonをマスターしよう

この記事で学んだPythonの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。