Java'daki mod sözdizimi nedir


231

Sözde kodda örnek olarak:

if ((a mod 2) == 0)
{
    isEven = true;
}
else
{
    isEven = false;
}

Yanıtlar:


357

Negatif olmayan tamsayılar için biraz farklı semantiğe sahip modulo operatörü yerine, kalan operatörü kullanabilirsiniz %. Tam örneğiniz için:

if ((a % 2) == 0)
{
    isEven = true;
}
else
{
    isEven = false;
}

Bu, bir astarla basitleştirilebilir:

isEven = (a % 2) == 0;

80
Eğer / else gerekli değilse, sadece isEven = (a% 2) == 0,
Steve Kuo

59
Mod ve modüler terimlerine dikkat edin çünkü n (mod m) HER ZAMAN> = 0, ancak% n değil. n% m> -m ve <m aralığındadır. Java'nın int ve long türleri için kalan bir operatörü olmasına rağmen, modül işlevi veya operatörü yoktur. Yani, -12% 10 = -2, -12 mod 10 = 8.% operatörü n% m için negatif bir değer döndürürse, (n% m) + m size n mod m verecektir. BigInteger her ikisi için de işlevler sağlar ve bunların özellikleri, farkı oldukça iyi açıklar. Ayrıca, sıfır ile dikkatli olun. Matematikte, sıfır çift sayı iken pozitif veya negatif DEĞİLDİR.
Jim

4
@ nl-x Muhtemelen, öncelik konusunda açık olmak konvansiyona bırakmaktan daha iyidir. Ben biri için %daha ==önce bakmadan önce değerlendirildiğini bilmiyordum , bu yüzden ifadenin (a%2)==0veya ile eşdeğer olup olmadığı belirsiz olacaktır a%(2==0). Bir booleanın tamsayı ile aynı olmadığı java'da daha az önemli
Matthew Sainsbury

8
Bu modül operatörü değil - geri kalan operatör. Lütfen yazıyı düzeltin!
Kieren Johnstone

2
boolean even = ((a & 1) == 0). Daha kolay.
mdev

111

İşte sahte kodunuzun en az Java kodunda gösterimi;

boolean isEven = a % 2 == 0;

Şimdi bileşenlerine ayıracağım. Java'daki modül operatörü yüzde karakteridir (%). Bu nedenle int% int almak başka bir int döndürür. Çift eşittir (==) operatörü, bir çift ints gibi değerleri karşılaştırmak için kullanılır ve bir boole döndürür. Bu daha sonra 'isEven' boole değişkenine atanır. Operatör önceliğine bağlı olarak, modül karşılaştırma öncesinde değerlendirilecektir.


12
minimal parantez olmadan olurdu;)
pstanton

3
Kalan bir operatör, bir modül operatörü değil.
Lorne Marquis

@ user207421 Adı aslında kalan işleç ama eşdeğer değil: " modül - 4. (hesaplama, programlama) Bu numaraların bölünmesinin kalanını almak için iki sayı arasına yerleştirilmiş bir operatör."?
GeroldBroser Monica

93

Herkes zaten cevabı verdiğinden, biraz ek bağlam ekleyeceğim. "modül" operatörü aslında geri kalan işlemi gerçekleştirmektedir. Mod ve rem arasındaki fark, ince ama önemlidir.

(-1 mod 2) normalde 1 verir. Daha spesifik olarak X ve Y olmak üzere iki tamsayı verildiğinde, işlem (X mod Y), [0, Y) aralığında bir değer döndürme eğilimindedir. Farklı bir şekilde söylendiğinde, X ve Y modülü her zaman sıfırdan büyük veya ona eşittir ve Y'den küçüktür.

"%" Veya rem operatörü ile aynı işlemi yapmak X değerinin işaretini korur. X negatifse, (-Y, 0] aralığında bir sonuç alırsınız. X pozitifse, [0, Y) aralığında bir sonuç alırsınız.

Genellikle bu ince ayrım önemli değildir. Yine de kod sorunuza geri dönersek, "eşitlik" için çözmenin birden fazla yolu vardır.

İlk yaklaşım yeni başlayanlar için iyidir, çünkü özellikle ayrıntılıdır.

// Option 1: Clearest way for beginners
boolean isEven;
if ((a % 2) == 0)
{
  isEven = true
}
else
{
  isEven = false
}

İkinci yaklaşım dilden daha iyi yararlanır ve daha özlü koda yol açar. (== operatörünün bir boole döndürdüğünü unutmayın.)

// Option 2: Clear, succinct, code
boolean isEven = ((a % 2) == 0);

Üçüncü yaklaşım tamlık için burada ve üçlü operatör kullanıyor . Üçlü operatör genellikle çok yararlı olmasına rağmen, bu durumda ikinci yaklaşımı daha üstün buluyorum.

// Option 3: Ternary operator
boolean isEven = ((a % 2) == 0) ? true : false;

Dördüncü ve son yaklaşım, tamsayıların ikili gösterim bilgisini kullanmaktır . En küçük anlamlı bit 0 ise sayı çifttir. Bu bitsel ve (&) operatörü kullanılarak kontrol edilebilir . Bu yaklaşım en hızlı olsa da (bölme yerine basit bit maskelemesi yapıyorsunuz), belki de yeni başlayanlar için biraz gelişmiş / karmaşıktır.

// Option 4: Bitwise-and
boolean isEven = ((a & 1) == 0);

Burada bitsel-ve operatörünü kullandım ve seçenek 2'de gösterilen kısa ve özlü formda temsil ettim. Seçenek 1'in formunda (ve alternatif olarak Seçenek 3'lerde) yeniden yazmak okuyucuya bir alıştırma olarak bırakılır. ;)

Umarım yardımcı olur.


Teşekkürler Rob. Bu karışıklık, programcılara matematiksel özelliklere sahip algoritmaların modüler aritmetikten nasıl uygulanacağını açıklamada büyük zorluklara neden olur. Kalan modül DEĞİLDİR, ancak kalanlardan hızlı bir şekilde bir modül türetilebilir.
Jim

1
@TickledPink Bunun Java'da derlenmemesi dışında.
Eugene Beresovsky

33

Java'nın% (REM) işleminin negatif X ve pozitif Y değerleri için MOD gibi çalışmasını sağlamak için şu yöntemi kullanabilirsiniz:

private int mod(int x, int y)
{
    int result = x % y;
    if (result < 0)
    {
        result += y;
    }
    return result;
}

veya üçlü operatörle (bazı durumlarda daha kısa, ancak mümkün değil veya daha az verimli):

private int mod(int x, int y)
{
    int result = x % y;
    return result < 0? result + y : result;
}

12

Java aslında C'nin yaptığı gibi hiçbir modulo operatörüne sahip değildir. Java'da%, kalan bir operatördür. Pozitif tamsayılarda, tam olarak modulo gibi çalışır, ancak negatif tamsayılarda farklı çalışır ve modulo'dan farklı olarak kayan nokta sayılarıyla da çalışabilir. Yine de,% değerini pozitif tamsayılardan başka bir şeyde kullanmak nadirdir, bu yüzden bir modulo olarak adlandırmak istiyorsanız, çekinmeyin!


Ama ben bir negatif mod tamsayı için çalışan gerçek bir modulo operatörü istiyorum, böylece array[x mod array.length]allways negatif pozisyonları endekslemek yerine benim dizi bir öğeye erişir.
Kris

2
(x % y + y) % y veya Java 8'den başlayarak,Math.floorMod(x, y)
Greg Charles

12

Değerin negatif olup olmadığını kontrol ederek uygun bir modulo yapmak ve eğer varsa (birçoklarının önerdiği gibi) düzeltmek mümkün olsa da, daha kompakt bir çözüm var.

(a % b + b) % b

Bu önce modulo'yu yapacak, değeri -b -> + b aralığına sınırlayacak ve daha sonra değerin pozitif olmasını sağlamak için b ekleyecek ve bir sonraki modüloyu 0 -> b aralığına sınırlayacaktır.

Not: b negatifse, sonuç da negatif olur


Bu, a ve b'nin her ikisi de büyük sayı olduğunda taşabilir, bu nedenle doğru bir çözüm değildir.
Trixie Wolf

11

Kod modulo kullanmadan çok daha hızlı çalışır:

public boolean isEven(int a){
    return ( (a & 1) == 0 );
}

public boolean isOdd(int a){
    return ( (a & 1) == 1 );
}

3
Bu, kabul edilen cevaptan çok daha temiz görünüyor. Bunun erken optimizasyonla bir ilgisi yoktur. Sadece daha iyi - eğer çalışırsa.
AlexWien

4
@LluisMartinez Bu, bilgisayar kullanımında en yanlış söylenen sözlerden biridir. Tam teklif şudur: "Programcılar, programlarının kritik olmayan bölümlerinin hızını düşünmek veya bunlardan endişe etmek için çok fazla zaman harcarlar ve bu verimlilik girişimlerinin hata ayıklama ve bakım dikkate alındığında gerçekten güçlü bir olumsuz etkisi vardır. verimlilik, zamanın yaklaşık% 97'sini söylüyor: erken optimizasyon tüm kötülüklerin köküdür. Yine de bu kritik% 3'teki fırsatlarımızı kaçırmamalıyız. " Bu aslında oldukça farklı bir şey anlamına geliyor.
Lorne Marquis

3
@EJP Muhtemelen haklısın. Bir test yaptım (1 milyon iterasyonlu döngü), modulo ile 4000 nanosaniye, mantıksal ve 2500 nanosaniye ile 2500 nanosaniye aldı.
Lluis Martinez

Bu neden bir cevap olsun ki? Elbette gariptir, ancak mod / kalan operatör ile hiçbir şey yapmaz. Soru, mod operatörünü anlatıyor, tek nasıl bile bulunacağını değil.
Mark Walsh



4

Java'da %operatör: 15.17.3. Kalan Operatör%

Ayrıca olduğunu unutmayın floorModiçinde java.lang.Mathfarklı bir sonuç verecek sınıfta %farklı işaretlerle bağımsız değişkenler için:

public static int floorMod​(int x, int y)


1
FloorMod, %argüman negatif olduğunda da düzgün çalıştığından daha iyi bir 'modulo' operatörü olduğu için seçildi . Diğer cevapların hiçbiri gerçekten doğru değildir, çünkü argümanlar pozitif olmadığı sürece% ifadesinin gerçekten modulo olmadığı anlamına gelmemektedir. Özellikle her tamsayıyı dizideki ardışık bir konuma eşlemek istiyorsanız array[floorMod(i, array.length), dizin inegatif bölgeye girse bile doğru şekilde çalışır . Öyle değil %.
Kris

3

Ayrıca, mod şu şekilde kullanılabilir:

int a = 7;
b = a % 2;

beşittir. Çünkü 7 % 2 = 1.


muhtemelen bir örnekte yeni başlayanlar için ve çıktı olmadan bileşik işleçleri kullanmak bir hatadır.
Stu Thompson

3

Java'da geri kalan operatör %ve modulo operatörü şu şekilde ifade edilebilir:

public int mod(int i, int j)
{
  int rem = i % j;
  if (j < 0 && rem > 0)
  {
    return rem + j;
  }
  if (j > 0 && rem < 0)
  {
    return rem + j;
  }
  return rem;
}

2

Diğerlerinin de belirttiği gibi, %(kalan) operatör matematiksel modmodülün çalışması / işlevi ile aynı değildir .

mod vs %

x mod nFonksiyon eşler xiçin naralığındadır [0,n).
Oysa x % noperatöre eşler xiçin naralığındadır (-n,n).

Matematiksel modül işlemini kullanmak için bir yönteme sahip olmak ve xbirinin önündeki işareti önemsememek için şunları kullanabilirsiniz:

((x % n) + n) % n

Belki bu resim daha iyi anlamaya yardımcı olur (başımı buralara sarmakta zorlandım)

resim açıklamasını buraya girin


1
Güzel çizim. Diğer bir karmaşıklık: bu, intdeğişkenin kendisinin 2 ^ 32 modülerliğini hesaba katmaz. floorModYöntemi doğru böyle yapıyor (ama eğer ek hesaplamalar gerekebilir nnegatiftir).
Maarten Bodewes

1

Başka bir yol:

boolean isEven = false;
if((a % 2) == 0)
{
    isEven = true;
}

Ancak en kolay yol hala:

boolean isEven = (a % 2) == 0;

@Steve Kuo'nun dediği gibi.


0

Olarak Java, mod işlemi gibi gerçekleştirilebilir:

Math.floorMod(a, b)

Not: mod işlemi farklıdır kalan işlem. Olarak Java, geri kalan işlem gibi gerçekleştirilebilir:

a % b

Tam olarak değil ... javadocu Math.floorMod()buna sahip: The floor modulus is x - (floorDiv(x, y) * y), has the same sign as the divisor y, and is in the range of -abs(y) < r < +abs(y).Yani matematiksel modülle tam olarak aynı değil. Ancak , aynı yöntemin If the signs of arguments are unknown and a positive modulus is needed it can be computed as (floorMod(x, y) + abs(y)) % abs(y).
Javadoc'unda

Bu doğru olabilir @WesternGun ama eğer sen modülü sonra olumlu olduğunu biliyoruz floorModbeklendiği gibi operasyon çalışır. Ayrıca floorModfor longdeğerleri vardır, aksi takdirde BigIntegerdaha büyük değerler vardır.
Maarten Bodewes

-1

Modulo operatörü% (yüzde işareti) şeklindedir. Düzgünlüğü test etmek veya genellikle 2 güç için modulo yapmak için, isEven =! (A & 1) gibi & (ve ve işleci) de kullanabilirsiniz.


-3

@Cody koduna bir alternatif:

Modül operatörünü kullanma:

bool isEven = (a % 2) == 0;

Ben daha az çoğaltma ve kullanılmayan esneklik çünkü bu yazma / marjinal olarak daha iyi bir kod olduğunu düşünüyorum. İncelemek için biraz daha fazla beyin gücü gerektirir, ancak isEventelafi eder.


2
Kalan bir operatör, bir modül operatörü değil.
Lorne Marquis

@EJP tamam. O zaman modül operatörü nedir?
TheRealChx101
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.