C#:指定した小数点以下の桁数でMath.Floor(切り捨て)とMath.Ceiling(切り上げ)を行う方法

目次

C#における小数点の丸め処理

C#のMath.Floor()メソッドとMath.Ceiling()メソッドは、それぞれ数値を切り捨て(床関数)、切り上げ(天井関数)して整数にするための標準的な関数です。

  • Math.Floor(10.7)10 になります。
  • Math.Ceiling(10.2)11 になります。

しかし、実務的な計算では、「小数点第3位以下を切り捨てたい」や「小数点第2位以下を切り上げたい」といった、整数(0桁)以外の位置での丸め処理が必要になることがよくあります。

C#の標準ライブラリには、Math.Floor(value, decimalPlaces) のような、桁数を指定できる組み込みメソッドは用意されていません。

この記事では、Math.Pow()(べき乗)を組み合わせて、指定した小数点以下の桁数でFloor(切り捨て)およびCeiling(切り上げ)を実現するロジックを解説します。


指定桁数で切り捨て (Math.Floor)

Math.Floorを使用して指定した桁数(例: dp桁)で切り捨てを行うには、以下のステップを実行します。

  1. Math.Pow(10, dp) を使い、10のdp乗(dp=2なら100)を計算します。
  2. 元の数値にこの乗数を掛け、小数点の位置をdp桁右にずらします。
  3. その結果に対して Math.Floor を適用し、小数点以下を切り捨てます。
  4. 最後に、1.で使った乗数で割り、小数点の位置を元に戻します。

コード例: Floor

例えば、複数のセンサーから取得したデータの平均値を計算し、小数点第3位以下を切り捨てて(第3位までを有効な数値として)記録するシナリオです。

using System;

public class FloorDecimalExample
{
    public static void Main()
    {
        double totalSensorValue = 845.6;
        int sensorCount = 13;
        
        // 845.6 / 13 = 65.046153846...
        double averageValue = totalSensorValue / sensorCount;

        // 小数点第3位 (dp=3) で切り捨てたい
        int decimalPlaces = 3;
        
        // 1. 10の3乗 (1000) を計算
        double multiplier = Math.Pow(10, decimalPlaces);

        // 2. 小数点をずらす (65.04615... * 1000 = 65046.15...)
        // 3. 切り捨て (Math.Floor(65046.15...) = 65046.0)
        // 4. 小数点を戻す (65046.0 / 1000 = 65.046)
        double flooredAverage = Math.Floor(averageValue * multiplier) / multiplier;

        Console.WriteLine($"計算結果 (生): {averageValue}");
        Console.WriteLine($"第3位で切り捨て: {flooredAverage}");
    }
}

出力結果:

計算結果 (生): 65.04615384615385
第3位で切り捨て: 65.046

指定桁数で切り上げ (Math.Ceiling)

Math.CeilingのロジックもFloorと全く同じですが、ステップ3で使用するメソッドがMath.Ceilingに変わります。

コード例: Ceiling

例えば、ある計算結果(65.04615...)を、小数点第3位までを含むように「切り上げる」必要がある場合のロジックです。

using System;

public class CeilingDecimalExample
{
    public static void Main()
    {
        double averageValue = 65.04615384615385; // 上記の例の計算結果
        int decimalPlaces = 3;
        
        double multiplier = Math.Pow(10, decimalPlaces); // 1000

        // 2. 小数点をずらす (65046.15...)
        // 3. 切り上げ (Math.Ceiling(65046.15...) = 65047.0)
        // 4. 小数点を戻す (65047.0 / 1000 = 65.047)
        double ceilingAverage = Math.Ceiling(averageValue * multiplier) / multiplier;

        Console.WriteLine($"計算結果 (生): {averageValue}");
        Console.WriteLine($"第3位で切り上げ: {ceilingAverage}");
    }
}

出力結果:

計算結果 (生): 65.04615384615385
第3位で切り上げ: 65.047

負の数の場合の動作

この手法の重要な点は、Math.Floor(負の無限大方向への丸め)とMath.Ceiling(正の無限大方向への丸め)の特性が、指定した桁数でも維持されることです。

これは、「0方向への切り捨て(Math.Truncate)」とは異なる動作になります。

using System;

public class NegativeExample
{
    public static void Main()
    {
        double negativeValue = -10.12345;
        int dp = 3;
        double multiplier = Math.Pow(10, dp); // 1000

        // -10.12345 * 1000 = -10123.45

        // Floor: -10123.45 より小さい整数 = -10124
        // -10124 / 1000 = -10.124
        double floored = Math.Floor(negativeValue * multiplier) / multiplier;

        // Ceiling: -10123.45 より大きい整数 = -10123
        // -10123 / 1000 = -10.123
        double ceiling = Math.Ceiling(negativeValue * multiplier) / multiplier;
        
        Console.WriteLine($"元の値: {negativeValue}");
        Console.WriteLine($"Floor (負の無限大方向): {floored}");
        Console.WriteLine($"Ceiling (正の無限大方向): {ceiling}");
    }
}

出力結果:

元の値: -10.12345
Floor (負の無限大方向): -10.124
Ceiling (正の無限大方向): -10.123

補足: decimal型での計算

Math.Pow()double型を扱うため、高精度が求められる金融計算(decimal型)には注意が必要です。decimal型でこのロジックを使用する場合、Math.Pow()の結果をdecimalにキャストするか、乗数を100m1000mのようにdecimalリテラルとして明示的に定義する方が安全です。

decimal price = 1.01234m;
decimal multiplier = 1000m; // 10の3乗

// Math.Floor は decimal にも対応している
decimal flooredPrice = Math.Floor(price * multiplier) / multiplier;

Console.WriteLine($"Decimal (Floor): {flooredPrice}"); // 1.012

まとめ

Math.FloorMath.Ceilingには桁数を指定する機能はありませんが、Math.Pow(または100mのような固定値)を使って「小数点をずらす → 丸める → 小数点を戻す」という手順を踏むことで、指定した桁数での切り捨て・切り上げを正確に実装できます。

このテクニックは、Math.Round(四捨五入)とは異なる、特定の方向への丸め処理(切り捨て・切り上げ)が必要な場合に不可欠です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次