閉じる

C#のMath.Floorで負の数を扱う際の注意点:Truncateとの違いと適切な使い分けを解説

C#を使用して数値計算プログラムを開発する際、端数の処理は避けて通れない重要なトピックです。

特に小数点以下を切り捨てる処理において、「Math.Floor」と「Math.Truncate」のどちらを使用すべきか迷う場面は少なくありません。

正の数を扱うだけであれば両者の結果は一致しますが、負の数が絡むと挙動が大きく異なるため、仕様を正しく理解しておく必要があります。

本記事では、2026年現在のC#開発においても重要となる、負の数における切り捨て処理の違いと適切な使い分けについて詳しく解説します。

C#における切り捨て処理の基本メソッド

C#の.NET環境では、System名前空間のMathクラスに多くの数学関数が用意されています。

端数処理に関連する代表的なメソッドとして、「Math.Floor」、「Math.Truncate」、「Math.Ceiling」の3種類が挙げられます。

開発者が意図した計算結果を得るためには、まずそれぞれのメソッドが「数直線上においてどの方向に数値を丸めるのか」を把握することが不可欠です。

Math.Floorメソッドの役割

Math.Floorメソッドは、指定した数値以下の最大の整数を返します。

数学的な定義では「床関数」と呼ばれ、常に数直線上の左方向(負の無限大方向)に向かって値を丸める性質を持っています。

正の数である「1.5」を渡した場合、1.5以下で最大の整数は「1」となるため、結果は1を返します。

Math.Truncateメソッドの役割

Math.Truncateメソッドは、数値の小数部分を単純に削除し、整数部分のみを残す処理を行います。

このメソッドは常に「0」の方向に向かって値を丸めるという特徴があります。

正の数である「1.5」を渡した場合、小数点以下の「.5」が取り除かれるため、結果はMath.Floorと同じ「1」になります。

負の数における挙動の違いを比較する

正の数では同じ結果を返す両メソッドですが、負の数を引数に渡すとその結果は明確に分かれます。

この挙動の違いを理解していないと、座標計算や金融系のシステムにおいて重大なバグを引き起こす原因となります。

負の数におけるMath.Floorの挙動

Math.Floorに「-1.5」を渡した場合、結果は「-2」となります。

これは、Math.Floorの定義が「引数以下の最大の整数」であるため、-1.5より小さい整数のうち最も大きいものである「-2」が選ばれるからです。

「切り捨て」という言葉からイメージする「絶対値が小さくなる方向」とは逆の動きをすることに注意が必要です。

負の数におけるMath.Truncateの挙動

対して、Math.Truncateに「-1.5」を渡した場合、結果は「-1」となります。

Math.Truncateは符号に関わらず単純に小数部を切り捨てるため、-1.5の「.5」を除去した結果である-1が返されます。

「0に近い方の整数へ丸める」という動作が、Math.Truncateの負の数における本質的な挙動です。

実行コードによる具体的な比較検証

実際にC#のコードを記述して、正の数と負の数でどのような出力差が出るかを確認してみましょう。

以下のサンプルコードでは、double型の数値に対して各メソッドを適用しています。

C#
using System;

class Program
{
    static void Main()
    {
        double positiveValue = 1.8;
        double negativeValue = -1.8;

        Console.WriteLine($"元の値 (正): {positiveValue}");
        Console.WriteLine($"Math.Floor: {Math.Floor(positiveValue)}");
        Console.WriteLine($"Math.Truncate: {Math.Truncate(positiveValue)}");

        Console.WriteLine();

        Console.WriteLine($"元の値 (負): {negativeValue}");
        Console.WriteLine($"Math.Floor: {Math.Floor(negativeValue)}"); // 小さくなる方向(-2)
        Console.WriteLine($"Math.Truncate: {Math.Truncate(negativeValue)}"); // 0に近い方向(-1)
    }
}
実行結果
元の値 (正): 1.8
Math.Floor: 1
Math.Truncate: 1

元の値 (負): -1.8
Math.Floor: -2
Math.Truncate: -1

実行結果から明らかなように、正の数ではどちらも「1」ですが、負の数では「-2」と「-1」という異なる結果が出力されています。

この1の差が、ループ処理の回数や配列のインデックス計算において致命的な差異を生むことになります。

各種メソッドの比較表

理解を深めるために、Math.Ceiling(天井関数)も含めた挙動の比較表を作成しました。

それぞれのメソッドが、正の数と負の数でどのように数値を処理するか整理して覚えましょう。

入力値Math.Floor (床)Math.Truncate (切り捨て)Math.Ceiling (天井)
1.2112
1.8112
-1.2-2-1-1
-1.8-2-1-1

表を見ると、負の数においてMath.TruncateとMath.Ceilingの結果が一致していることがわかります。

これはMath.Ceilingが「指定した数値以上の最小の整数」を返す(数直線上の右方向へ進む)ためです。

実務における適切な使い分けの基準

では、私たちはどのような基準でこれらのメソッドを使い分けるべきでしょうか。

選択を誤らないためのガイドラインを提示します。

Math.Floorを選択すべきケース

Math.Floorは、「常に一定の方向(負の無限大)へ数値を丸めたい場合」に適しています。

例えば、グリッド状のマップシステムにおいて座標を計算する場合、負の領域であっても一貫して「下の境界線」を取得する必要があります。

また、周期的な計算や、余り(モジュロ演算)と組み合わせて使用する場合には、Floorの方が数学的に整合性が取りやすい傾向にあります。

Math.Truncateを選択すべきケース

Math.Truncateは、「符号を維持したまま、単に整数部分だけを抽出したい場合」に使用します。

ユーザーインターフェース上で「入力された数値の小数点以下を単に無視して表示する」といった要件がある場合に適しています。

また、多くのプログラミング言語における「int型へのキャスト」による切り捨てと同じ挙動を期待する場合も、Truncateが最も自然な選択肢となります。

浮動小数点数演算における注意点

C#でMathクラスを使用する際は、型による精度問題についても考慮しなければなりません。

Math.FloorやMath.Truncateはdouble型とdecimal型の両方のオーバーロードを持っています。

金融計算など、厳密な精度が求められるアプリケーションでは、必ずdecimal型を使用するようにしてください。

double型(浮動小数点数)は内部的にバイナリで近似値を保持するため、微小な誤差が発生し、期待した切り捨て結果にならないリスクがあるからです。

C#
// double型による精度の問題が生じる可能性のある例
double val = 0.9999999999999999;
Console.WriteLine(Math.Floor(val)); // 1 と出力される場合がある

// decimal型であればより正確に扱える
decimal dVal = 0.9999999999999999m;
Console.WriteLine(Math.Floor(dVal)); // 0 と出力される

このように、数値の性質や求められる精度に応じて適切なデータ型を選択することも、テクニカルな観点では非常に重要です。

まとめ

C#におけるMath.FloorとMath.Truncateの違いは、特に負の数を扱う際において顕著になります。

Math.Floorは「その数以下の最大の整数(負の無限大方向)」を目指し、Math.Truncateは「小数部を除去する(0の方向)」ことを目的とします。

「切り捨て」という言葉の曖昧さに頼らず、それぞれのメソッドが数直線上でどのように値を移動させるのかをイメージすることが、バグのないプログラムへの第一歩です。

用途に応じてこれらを正しく使い分け、意図した通りの数値処理を実現しましょう。

URLをコピーしました!