web-gelistirme-sc.com

Negatif sayılarla Modulo işlemi

Bir c programında aşağıdaki işlemleri deniyordum (Sadece davranışları kontrol etmek için)

 x = 5 % (-3);
 y = (-5) % (3);
 z = (-5) % (-3); 

printf("%d ,%d ,%d", x, y, z); 

çıktı gcc olarak (2, -2 , -2) olarak verdi. Her seferinde olumlu bir sonuç bekliyordum. Bir modül negatif olabilir mi? Birisi bu davranışı açıklayabilir mi?

151
Alva

C99 zorunlua/b gösterilebilir olduğunda:

(a/b) * b+a%ba değerine eşit olmalıdır

Bu mantıklı, mantıklı. Sağ?

Bunun neye yol açtığını görelim:


Örnek A. 5/(-3): -1

=> (-1) * (-3)+5%(-3) = = 5

Bu sadece 5%(-3) 2 ise olabilir.


Örnek B. (-5)/3, -1

=> (-1) * 3+(-5)%3 = -5

Bu sadece, (-5)%3-2 ise olabilir.

132
ArjunShankar

C'deki % operatörü modulo operator değil remainder operator.

Modulo ve kalan operatörler, negatif değerlere göre farklılık gösterir. 

Bir geri kalan operatör ile, sonucun işareti temettü işareti ile aynı iken, bir modulo operatör ile sonucun işareti bölen ile aynıdır.

C, % için a % b işlemini şöyle tanımlar:

  a == (a / b * b) + a % b

/ ile tamsayı bölümü 0 yönüne doğru kısalır. Bu, 0 'u bir modulo operatöründen ziyade bir işleç operatörü olarak tanımlayan %' a (ve negatif belirsizliğe değil) doğru yapılan kısaltmadır.

111
ouah

C99 Spesifikasyonuna göre: a = (a / b) * b + a % b

(a % b) = a - (a / b) * b! 'Yi hesaplamak için bir fonksiyon yazabiliriz!

int remainder(int a, int b)
{
    return a - (a / b) * b;
}

Modulo işlemi için aşağıdaki fonksiyona sahip olabiliriz (b> 0 varsayarak)

int mod(int a, int b)
{
    int r = a % b;
    return r < 0 ? r + b : r;
}

Sonucum (C% 'si) bir geri kalan operatör ve NOT modulo operatör.

56
dewang

Sayının negatif olup olmadığını kontrol etmenin bir gereği olmadığını sanmıyorum.

Pozitif modülü bulmak için basit bir fonksiyon bu olacaktır -

int modulo(int x,int N){
    return (x % N + N) %N;
}

N'nin pozitif olduğunu varsayalım, bu, x'in {hem pozitif hem de negatif değerleri için işe yarar.

Not; Ayrıca @chux tarafından belirtildiği gibi, eğer x ve N, sırasıyla INT_MAX-1 ve INT_MAX gibi bir şeye erişebilirlerse, int komutunu long long int ile değiştirin.

Ve eğer onlar da uzun süredir sınırları aşıyorsa (yani, LLONG_MAX'a yakın), diğer cevaplarda da açıklandığı gibi ayrı ayrı pozitif ve negatif durumları ele almalısınız.

39
Udayraj Deshmukh

Diğer cevaplar C99 veya daha sonra, negatif operand içeren tam sayıların bölünmesini her zaman sıfıra doğru kes olarak açıkladı. 

C89 öğelerinde, sonucun yukarı ya da aşağı doğru sonuçlanmasının uygulama tarafından tanımlandığını unutmayın. (a/b) * b + a%b tüm standartlarda a değerine eşit olduğundan, negatif işlenenleri içeren % sonucu C89'da uygulama tarafından tanımlanmıştır.

7
Yu Hao

Bir modül negatif olabilir mi? 

%, kalan işleci , bölmeden sonraki kalan, değil Euclidean_division . C99'dan beri sonuç 0, negatif veya pozitif olabilir.

 // a % b
 7 %  3 -->  1  
 7 % -3 -->  1  
-7 %  3 --> -1  
-7 % -3 --> -1  

Her seferinde olumlu bir sonuç bekliyordum.

a/b tanımlandığında iyi tanımlanmış bir Euclidean modulo gerçekleştirmek için a,b herhangi bir işarete sahiptir ve sonuç hiçbir zaman negatif olmaz:

int modulo_Euclidean(int a, int b) {
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}

modulo_Euclidean( 7,  3) -->  1  
modulo_Euclidean( 7, -3) -->  1  
modulo_Euclidean(-7,  3) -->  2  
modulo_Euclidean(-7, -3) -->  2   
3
chux

Modulo işleminin sonucu pay işaretine bağlıdır ve bu nedenle y ve z için -2 elde edersiniz.

İşte referans

http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_14.html

Tamsayılı Bölümü

Bu bölümde tamsayı bölme gerçekleştirmek için işlevler açıklanmaktadır. Bu işlevler GNU C kütüphanesinde gereksizdir, çünkü GNU C. '/' operatörü daima sıfıra doğru yuvarlar. Ancak diğer C uygulamalar, '/' olumsuz argümanlarla farklı şekilde yuvarlanabilir . div ve ldiv, faydalıdır çünkü, bölüm: sıfıra doğru. Kalan kısımda da aynı işaret var. payı.

3
Kartik Anand

Bu sözleşmelerin kaynaklandığı Matematik'te, modulo aritmetiğinin olumlu bir sonuç vermesi gerektiği iddiası yoktur.

Örneğin. 

1 mod 5 = 1, fakat -4'e eşit olabilir. Yani, 1/5, 0'dan 0 veya -4'e bir geri kalan 1 verir. (Her iki 5 faktörü)

Benzer şekilde, -1 mod 5 = -1, fakat aynı zamanda 4'e de eşit olabilir. -1/5, -5'ten 0 veya 4'e bir geri kalan -1 verir. (Her iki faktör 5)

Daha fazla okumak için denklik sınıflarına Matematikte bakın. 

2
DarkPurple141

C99 standardına göre , bölüm 6.5.5 Çarpma operatörleri, aşağıdakileri gerektirir:

(a / b) * b + a % b = a

Sonuç

Bir geri kalan işlemin sonucunun işareti, C99'a göre., Temettü ile aynıdır.

Bazı örnekleri görelim (dividend / divisor):

Yalnızca temettü olumsuz olduğunda

(-3 / 2) * 2  +  -3 % 2 = -3

(-3 / 2) * 2 = -2

(-3 % 2) must be -1

Sadece bölen negatif olduğunda

(3 / -2) * -2  +  3 % -2 = 3

(3 / -2) * -2 = 2

(3 % -2) must be 1

Hem bölen hem de temettü olumsuz olduğunda

(-3 / -2) * -2  +  -3 % -2 = -3

(-3 / -2) * -2 = -2

(-3 % -2) must be -1

6.5.5 Çarpma operatörleri

Sözdizimi

  1. çarpımsal ifade:
    • cast-expression
    • multiplicative-expression * cast-expression
    • multiplicative-expression / cast-expression
    • multiplicative-expression % cast-expression

Kısıtlamalar

  1. İşlenenlerin her biri aritmetik tipte olacaktır. % operatörünün işlenenleri tam sayı türünde olmalıdır.

Semantik

  1. Her zamanki aritmetik dönüşümler operandlar.

  2. * Operatörünün sonucu, .__ 'nın bir ürünüdür. operandlar.

  3. / Operatörünün sonucu, .__ 'dan gelen bölümdür. birinci işlenenin ikinci bölüme ayrılması; % operatörünün sonucu kalandır. Hem de İşlemler, ikinci işlenenin değeri sıfır ise, Davranış tanımsız.

  4. Tamsayılar bölündüğünde, / operatör .__ 'nın sonucu. Herhangi bir kesirli kısım ile cebirsel bir bölümdür. atıldı [1]. Bölüm a/b temsil edilebilir ise, (a/b)*b + a%b ifadesi a işlevine eşit olmalıdır.

[1]: Buna genellikle "sıfıra doğru kısma" denir.

1

Modulus operatörü kalanı verir . c Modulus operatörü genelde numaratörün işaretini alır.

  1. x = 5% (-3) - burada pay olumludur, dolayısıyla 2 olur.
  2. y = (-5)% (3) - burada pay negatif, dolayısıyla -2
  3. z = (-5)% (-3) - burada pay negatiftir, sonuç -2'dir.

Ayrıca modül (kalan) operatörü sadece tamsayı tipinde kullanılabilir ve kayan nokta ile kullanılamaz.

1
Kavya

Modulo operatörü, sayı pozitif olduğunda mod operatörü gibidir, fakat sayı negatifse farklıdır.

Sorunlarda birçok kez bizden modulo 10 ^ 9 + 7 cevabını vermemiz istenir.

Cevabı (modulo kullanmadan önce) 'a' ile belirtin.

Basit Basit Kural -

a pozitif ise, o zaman bir modulo 10 ^ 9 + 7 =a% (10 ^ 9 + 7)

a negatif ise, o zaman bir modulo 10 ^ 9 + 7 =(% a (10 ^ 9 + 7)) + (10 ^ 9 + 7)

Bu tür problemlerde, döngünün herhangi bir basamağının, tamsayı aralığının dışındaki bir değeri hesaplayabildiğini tespit edersek (tamsayı kullanıyorsak), o zaman modulo operatörünü o adımda kullanabiliriz. Son cevap, modulo operatörünü sadece bir kez kullanmışız gibi olacaktır.

Bunun sebebi- (a * b)% c = ((a% c) (b% c))% c Aynı toplama ve çıkarma için de geçerlidir.

0
Akash Bhalotia

Ben soyut aritmetik olarak tanımlandığı gibi mod düşünmek daha yararlı olduğuna inanıyorum; bir işlem olarak değil, farklı elemanlarla ve farklı operatörlerle tamamen farklı bir aritmetik sınıfı olarak. Bu, mod 3 içindeki toplama işleminin "normal" ekleme ile aynı olmadığı anlamına gelir; yani; tamsayı ekleme.

Yani ne zaman yaparsın:

5 % -3

integer 5'i mod -3 kümesindeki bir öğeyle eşlemeye çalışıyorsunuz. Bunlar mod -3 öğelerinin öğeleridir:

{ 0, -2, -1 }

Yani:

0 => 0, 1 => -2, 2 => -1, 3 => 0, 4 => -2, 5 => -1

30 saat nedense kalmak zorunda kalsın, o gün kaç saat kalacaksın? 30 mod -24.

Fakat C'nin uyguladığı şey mod değil, geri kalanı. Her neyse, mesele şu ki, negatifleri geri getirmenin bir anlamı var.

0
FelipeC