C#の整数の除算とモジュロを計算するにはどうすればよいですか?


87

C#で整数の除算とモジュロを計算するにはどうすればよいですか?


16
これは基本的すぎるかもしれませんが、それは本当の質問です...

2
演算子がC#のモジュラス演算子ではない理由についての関連記事と必読のブログ%
RBT 2017

回答:


124

この種の質問をする前に、チェックしてください MSDNのドキュメント

2つの整数を除算すると、結果は常に整数になります。たとえば、7/3の結果は2です。7/ 3の剰余を決定するには、剰余演算子()を使用します。

int a = 5;
int b = 3;

int div = a / b; //quotient is 1
int mod = a % b; //remainder is 2

10
%は、モジュラスではなく剰余を返します(ご指摘のとおり)。それらは同じものを使用せず、異常なケース(負のインデックスなど)を処理するときに問題を引き起こす可能性があります。ただし、たとえば、弱正のインデクサーの10回ごとの反復を探す場合は、モジュラス演算子のように使用できます。おそらく、実際の弾性率を計算する方法を説明できますか?
cor_Blimey 2012

1
確かに、私はこのような投稿を読みましたが、アプリケーションに問題がありました:)
黙示録2013

1
...正確には何の宣言のポイントであるabあなたがそれらを使用しない場合は?:D
leviathanbadger 2013

1
おそらく、ユーザーは(私のように)DivRem関数を検索していたので、質問は一見したほど簡単ではない可能性があります。ありがとう@ danodonovan
Tancredi18年

1
他の人も指摘しているように、答えはこの答えが主張するほど単純ではなく、デバッグが難しい間違いにつながる可能性があります。参照してください/programming/10065080/mod-explanation
SansWit

90

もあります Math.DivRem

quotient = Math.DivRem(dividend, divisor, out remainder);

2
これは、商と剰余を1つの関数で提供するため、私の意見では正解です。どちらのアプローチが優れているかはわかりませんが(「a / b」を使用して商を取得し、次に「a%b」を使用して剰余またはMath.DivRemを取得)、このアプローチは確かに読みやすくなっています(私の場合は必要です)商と剰余の両方を知るために)-ありがとう!
イゴール

2
@Igorありがとう、元の質問に答えたとき、この関数は存在しませんでした!ただし、この関数の存在により、ドキュメントのチェックに関するas-ciiの発言は少しばかげているように見えます。...:)
danodonovan 2015

6
混乱を避けるために、Math.DivRem1回の操作でdivとmodを計算しません。これは単なるヘルパー関数であり、そのソースコードは正確に次のとおりですpublic static int DivRem(int a, int b, out int result) { result = a%b; return a/b; }
nightElfik 2016年

9
@NightElfik実装は将来変更される可能性があり、ランタイムは、互いに素divrem命令するよりも、最適化のためのメソッド呼び出しを識別する方が簡単です
kbolino 2016年

6
@kbolino少なくとも.NETCoreでは、除算と減算変更されいるため、これすばらしい予測です。また、RyuJITでは、単一のx86 div命令を使用するようにさらに最適化が計画されていますが、JITの変更では、個別に使用する場合は%/演算子も検出する必要があります。
ボブ

15

楽しい事実!

「モジュラス」演算は次のように定義されます。

a % n ==> a - (a/n) * n

参照:モジュラー算術

したがって、組み込みの%演算子よりもはるかに遅くなります、独自にロールすることができます。

public static int Mod(int a, int n)
{
    return a - (int)((double)a / n) * n;
}

編集:うわー、元々ここでかなりひどいミスポーク、私を捕まえてくれてありがとう@joren

ここで、C#のdivision + cast-to-intは同等であるMath.Floor(つまり、分数を削除する)という事実に依存していますが、「真の」実装は代わりに次のようになります。

public static int Mod(int a, int n)
{
    return a - (int)Math.Floor((double)a / n) * n;
}

実際、%と「真の係数」の違いは次のようにわかります。

var modTest =
    from a in Enumerable.Range(-3, 6)
    from b in Enumerable.Range(-3, 6)
    where b != 0
    let op = (a % b)
    let mod = Mod(a,b)
    let areSame = op == mod
    select new 
    { 
        A = a,
        B = b,
        Operator = op, 
        Mod = mod, 
        Same = areSame
    };
Console.WriteLine("A      B     A%B   Mod(A,B)   Equal?");
Console.WriteLine("-----------------------------------");
foreach (var result in modTest)
{
    Console.WriteLine(
        "{0,-3} | {1,-3} | {2,-5} | {3,-10} | {4,-6}", 
        result.A,
        result.B,
        result.Operator, 
        result.Mod, 
        result.Same);
}

結果:

A      B     A%B   Mod(A,B)   Equal?
-----------------------------------
-3  | -3  | 0     | 0          | True  
-3  | -2  | -1    | -1         | True  
-3  | -1  | 0     | 0          | True  
-3  | 1   | 0     | 0          | True  
-3  | 2   | -1    | 1          | False 
-2  | -3  | -2    | -2         | True  
-2  | -2  | 0     | 0          | True  
-2  | -1  | 0     | 0          | True  
-2  | 1   | 0     | 0          | True  
-2  | 2   | 0     | 0          | True  
-1  | -3  | -1    | -1         | True  
-1  | -2  | -1    | -1         | True  
-1  | -1  | 0     | 0          | True  
-1  | 1   | 0     | 0          | True  
-1  | 2   | -1    | 1          | False 
0   | -3  | 0     | 0          | True  
0   | -2  | 0     | 0          | True  
0   | -1  | 0     | 0          | True  
0   | 1   | 0     | 0          | True  
0   | 2   | 0     | 0          | True  
1   | -3  | 1     | -2         | False 
1   | -2  | 1     | -1         | False 
1   | -1  | 0     | 0          | True  
1   | 1   | 0     | 0          | True  
1   | 2   | 1     | 1          | True  
2   | -3  | 2     | -1         | False 
2   | -2  | 0     | 0          | True  
2   | -1  | 0     | 0          | True  
2   | 1   | 0     | 0          | True  
2   | 2   | 0     | 0          | True  

「ここでは、C#の整数除算がMath.Floorと同等である(つまり、分数を削除する)という事実に依存しています」-しかし、そうではありません。整数除算はゼロに向かって丸められ、Math.Floorは負の無限大に向かって丸められます。
Joren 2013年

@Joren申し訳ありませんが、いいえ-これを実行してみてください:Enumerable.Range(0, 10).Select(x => (double)x / 10.0).Select(x => (int)x).ToList().ForEach(x => Console.WriteLine(x));-すべて0
JerKimball 2013年

2
まず、整数除算について話します。浮動小数点除算を実行してから整数にキャストした場合に何が起こるかは関係ありません(同じ結果が得られたとしても)。次に、0から9までの整数が、10で除算して整数部分に切り捨てられた後、0以外のものを与えると予想される理由がわかりません。それが1になった場合は丸められること離れて、ゼロからまたはに向けての無限大。第三に、正の数の場合、ゼロへの丸めと負の無限大への丸めの間に違いまったくないため、問題に対処することすらできません。
Joren 2013年

Math.Floor(-10.0 / 3.0)と同じもので-10 / 3はありません
Joren 2013年

@jorenああ、ここで切断が表示されます-いいえ、整数除算を実行していません。二重除算を実行してから、結果を整数にキャストしています-非常に異なります。
JerKimball 2013年

14

除算は、次の/演算子を使用して実行されます。

result = a / b;

モジュロ除算は、次の%演算子を使用して行われます。

result = a % b;

1
+1:便利なことに型を省略すると、より良い答えになります:-)これは4.0のSystem.Numeric.BigIntegerでも機能すると思います。

5
%-> Cor_Blimeyが言ったように、モジュラスではなく剰余を返します。例:(-5%3)== -2 [C#]、-5 mod 3 = 1 [wolframalpha.com]。
黙示録2013

2
注:モジュロはモジュラスと同じではありません。モジュロは余り、モジュラスは絶対値です。
ライアン

-4

ユーザーから2つの整数を読み取ります。次に、剰余と商を計算/表示します。

// When the larger integer is divided by the smaller integer
Console.WriteLine("Enter integer 1 please :");
double a5 = double.Parse(Console.ReadLine());
Console.WriteLine("Enter integer 2 please :");
double b5 = double.Parse(Console.ReadLine());

double div = a5 / b5;
Console.WriteLine(div);

double mod = a5 % b5;
Console.WriteLine(mod);

Console.ReadLine();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.