C#での整数の除算時にFloor・Ceilした値を返す (正値・負値全ての範囲版)

# はじめに

正値の範囲において、整数の除算を行った結果をFloor・Ceilしたい時は、下記の記事の簡単な式で算出可能になります。

https://qiita.com/dl_from_scratch/items/9b74bb3ecd97dddaadcc

本稿では、正値・負値全ての範囲に拡大させた場合を考えてみます。

# 整数の除算時にFloor・Ceil (正値・負値全ての範囲版)

整数の除算「整数 / 整数」は、正負の間で特性が変わるので(下記の記事: 正の範囲ではFloorの値、負の範囲ではCeilの値と同じ)、正側と負側で算出式を切り替える必要があることが分かります。

https://qiita.com/dl_from_scratch/items/b55ec179729a0e215a7a

下記の算出式を、正側と負側で正負を考慮しながら切り替えて、整数の除算を行った結果をFloor・Ceilする関数を作成すると、

>正値の範囲において、整数の除算を行った結果をFloor・Ceilしたい時、
> * Floorは、c = a / b
> * Ceilは、c = (a - 1) / b + 1

整数の除算を行った結果をFloorする時は、

```C#
// 整数の除算時にFloorした値を返す floor(a / b)
// 整数除算でFloorの値を作る 正値・負値の双方の範囲で利用可
public static int IntFloor(int a, int b) {
    return a >= 0 ? 
        a / b : // 正値の整数除算はfloor値となる
        (a + 1) / b - 1; // 負値の整数除算をfloor値となるように+1,/,-1でシフト
}
```

整数の除算を行った結果をCeilする時は、

```C#
// 整数の除算時にCeilした値を返す ceil(a / b)
// 整数除算でCeilの値を作る 正値・負値の双方の範囲で利用可
public static int IntCeil(int a, int b) {
    return a >= 1 ?
        (a - 1) / b + 1 : // 整数除算をceil値となるように-1,/,+1でシフト
        a / b; // 負値の整数除算はゼロ側へfloor値となる
}
```

# テストコード

```C#:Program 2302-4 整数除算 負値を含む.cs
using System;

namespace ConsoleApp1 {
    class Program {
        static void Main(string[] args) {
            /* 結果: 
▼整数除算でFloorの値を作る 正値・負値の双方の範囲で利用可
int:  7 / 3 =  2
int:  6 / 3 =  2
int:  5 / 3 =  1
int:  4 / 3 =  1
int:  3 / 3 =  1
int:  2 / 3 =  0
int:  1 / 3 =  0
int:  0 / 3 =  0
int: -1 / 3 = -1
int: -2 / 3 = -1
int: -3 / 3 = -1
int: -4 / 3 = -2
int: -5 / 3 = -2
int: -6 / 3 = -2
int: -7 / 3 = -3

▼整数除算でCeilの値を作る 正値・負値の双方の範囲で利用可
int:  7 / 3 =  3
int:  6 / 3 =  2
int:  5 / 3 =  2
int:  4 / 3 =  2
int:  3 / 3 =  1
int:  2 / 3 =  1
int:  1 / 3 =  1
int:  0 / 3 =  0
int: -1 / 3 =  0
int: -2 / 3 =  0
int: -3 / 3 = -1
int: -4 / 3 = -1
int: -5 / 3 = -1
int: -6 / 3 = -2
int: -7 / 3 = -2
            */

            Action<string> WL = Console.WriteLine; // 短縮

            WL("▼整数除算でFloorの値を作る 正値・負値の双方の範囲で利用可");
            var a = 7;
            var b = 3;
            for (; a >= -7; a--) {
                var c = IntDiv.IntFloor(a, b);
                WL($"int: {a,2} / {b} = {c,2}");
            }
            WL("");

            WL("▼整数除算でCeilの値を作る 正値・負値の双方の範囲で利用可");
            a = 7;
            b = 3;
            for (; a >= -7; a--) {
                var c = IntDiv.IntCeil(a, b);
                WL($"int: {a,2} / {b} = {c,2}");
            }
        }
    }

    // 整数除算でFloor/Ceilの値を作ったもの
    public static class IntDiv {

        // 整数の除算時にFloorした値を返す floor(a / b)
        // 整数除算でFloorの値を作る 正値・負値の双方の範囲で利用可
        public static int IntFloor(this int a, int b) {
            return a >= 0 ? 
                a / b : // 正値の整数除算はfloor値となる
                (a + 1) / b - 1; // 負値の整数除算をfloor値となるように+1,/,-1でシフト
        }

        // 整数の除算時にCeilした値を返す ceil(a / b)
        // 整数除算でCeilの値を作る 正値・負値の双方の範囲で利用可
        public static int IntCeil(this int a, int b) {
            return a >= 1 ?
                (a - 1) / b + 1 : // 整数除算をceil値となるように-1,/,+1でシフト
                a / b; // 負値の整数除算はゼロ側へfloor値となる
        }
    }
}
```

# 環境
Microsoft Visual Studio Community 2019 Version 16.11.22
VisualStudio.16.Release
Microsoft .NET Framework
Version 4.8.04084
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606924/a80b2b96-ebec-1c6b-a5a2-700f34441206.png)