C # 'da tamsayılar için bölme ve moduloyu nasıl hesaplayabilirim?


87

C # 'da tam sayılar için bölme ve moduloyu nasıl hesaplayabilirim?


16
Bu çok basit olabilir, ama gerçek bir soru ...

2
İlgili bir mesaj ve bir okumalı blog neden %operatörüdür değil C # modülü operatörü.
RBT

Yanıtlar:


124

Bu tür sorular sormadan önce lütfen MSDN belgelerine bakın .

İki tamsayıyı böldüğünüzde, sonuç her zaman bir tam sayıdır. Örneğin, 7 / 3'ün sonucu 2'dir. 7 / 3'ün kalanını belirlemek için, kalan operatörünü ( % ) kullanın.

int a = 5;
int b = 3;

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

10
% modülü değil kalanı verir (sizin de belirttiğiniz gibi). Aynı şey değildirler ve olağandışı durumlarla uğraşırken sorunlara neden olabilirler (örneğin negatif indeksler). Ancak, örneğin zayıf pozitif bir indeksleyicinin her 10'uncu yinelemesini ararken modül operatörü gibi kullanılabilir. Belki gerçek modülü nasıl hesaplayacağınızı açıklayabilirsiniz?
Cor_Blimey

1
Doğru, bunun gibi gönderileri okudum ve başvurumda sorunlar yaşadım :)
apocalypse

1
... Tam olarak beyan etmenin amacı nedir ave bbunları kullanmayacaksanız? : D
leviathanbadger

1
Belki de kullanıcı (benim gibi) bir DivRem işlevi arıyordu, bu nedenle soru ilk bakışta göründüğü kadar önemsiz olmayabilir. Teşekkürler @danodonovan
Tancredi

1
Diğerlerinin de belirttiği gibi cevap, bu cevabın iddia ettiği kadar basit değildir ve hata ayıklaması zor hatalara yol açabilir. Bkz. Https://stackoverflow.com/questions/10065080/mod-explanation
SansWit

90

Ayrıca birde şu var Math.DivRem

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

2
Bence bu doğru cevap olmalı, çünkü bölümü VE kalanı tek bir işlevde sağlıyor. Hangi yaklaşımın daha iyi performans gösterdiğinden emin değilim (bölüm elde etmek için "a / b" yi ve kalanı veya Math.DivRem'i elde etmek için "a% b" yi kullanarak), ancak bu yaklaşım kesinlikle okumak için çok daha güzel (benim durumumda ihtiyacım var hem bölümü hem de kalanı bilmek için) - teşekkür ederim!
Igor

2
@Igor teşekkürler, orijinal soru cevaplandığında bu işlev yoktu! Bununla birlikte, işlevin varlığı, as-cii'nin dokümantasyonu kontrol etme konusundaki açıklamasını biraz aptalca gösteriyor .... :)
danodonovan

6
Karışıklığı önlemek için Math.DivRemdiv ve mod'u tek bir işlemde hesaplamaz. Bu sadece bir yardımcı fonksiyonudur ve kaynak kodu tam olarak: public static int DivRem(int a, int b, out int result) { result = a%b; return a/b; }.
NightElfik

9
@NightElfik Uygulama gelecekte değişebilir ve çalışma zamanının optimizasyon için bir yöntem çağrısı belirlemesi ayrık divve remtalimatlardan daha
kolaydır

6
@kbolino Bu harika tahmin beri var o olmuştur değişti bölmek & çıkarmak, en azından .NET Core,. RyuJIT'te tek bir x86 div talimatı kullanmak için planlanan başka optimizasyonlar da var, ancak kuşkusuz JIT değişiklikleri, tek tek kullanıldığında %ve /operatörlerini de algılamalıdır .
Bob

15

Eğlenceli gerçek!

"Modül" işlemi şu şekilde tanımlanır:

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

Ref: Modüler Aritmetik

Eğer Yani olabilir o FAR yavaş% operatörü inşa daha olacak rağmen, kendi rulo:

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

Düzenleme: vay, aslında burada oldukça kötü bir şekilde yanlış konuştu, beni yakaladığın için teşekkürler @joren

Şimdi burada C # 'da division + cast-to-int'in eşdeğer olduğuna güveniyorum Math.Floor(yani, kesri düşürüyor), ancak "gerçek" bir uygulama bunun yerine şöyle bir şey olurdu:

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

Aslında,% ve "gerçek modül" arasındaki farkları aşağıdakilerle görebilirsiniz:

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);
}

Sonuçlar:

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  

"Şimdi burada, C #'daki tamsayı bölmesinin Math.Floor'a eşdeğer olduğu gerçeğine güveniyorum (yani, kesri düşüyor)" - Ama değil. Tamsayı bölme sıfıra doğru yuvarlanır, Matematik. Zemin negatif sonsuza yuvarlanır.
Joren

@Joren Üzgünüz, ama hayır - şunu çalıştırmayı deneyin: Enumerable.Range(0, 10).Select(x => (double)x / 10.0).Select(x => (int)x).ToList().ForEach(x => Console.WriteLine(x));- all
0'lar

2
İlk olarak, tamsayı bölmesinden bahsediyorum . Bir kayan noktalı bölme yapıp ardından tam sayıya çevirirseniz ne olacağı önemsizdir (aynı sonucu verse bile). İkinci olarak, neden 0 ile 9 arasındaki tam sayıların 10'a böldükten ve tamsayı kısmına kısaltıldıktan sonra 0'dan başka bir şey vermesini beklediğinizden emin değilim. Bu, 1 ile sonuçlansaydı , sıfırdan uzağa veya pozitif sonsuza yuvarlanırdı . Üçüncüsü, pozitif sayılar için sıfıra yuvarlama ile negatif sonsuza yuvarlama arasında hiçbir fark yoktur , bu yüzden sorunu ele bile almıyorsunuz.
Joren

Math.Floor(-10.0 / 3.0)ve -10 / 3vardır değil aynı şey.
Joren

@joren ah, burada kopukluğu görüyorum - hayır, tamsayı bölme yapmıyorum , çift bölme yapıyorum, sonra sonucu tam sayıya atıyorum - çok farklı.
JerKimball

14

Bölme, /operatör kullanılarak gerçekleştirilir :

result = a / b;

Modulo bölümü %operatör kullanılarak yapılır :

result = a % b;

1
+1: Uygun bir şekilde yazıyı dışarıda bırakmak daha iyi bir cevap yapar :-) Bunun 4.0'da System.Numeric.BigInteger ile de çalıştığına inanıyorum.

5
Cor_Blimey'in dediği gibi% ->, modülü değil, kalanını döndürür. Örneğin: (-5% 3) == -2 [C #], -5 mod 3 = 1 [wolframalpha.com].
apocalypse

2
Not: Modulo, Modulus ile aynı değildir. Modulo kalan kısım, Modül ise mutlak değerdir.
Ryan

-4

Kullanıcıdan iki tamsayı okuyun. Sonra kalanı ve bölümü hesaplayın / görüntüleyin,

// 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();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.