Javada yaptığın zaman
a % b
Eğer a negatifse, olması gerektiği gibi b'ye sarmak yerine negatif bir sonuç döndürür. Bunu düzeltmenin en iyi yolu nedir? Düşünebilmemin tek yolu
a < 0 ? b + a : a % b
Javada yaptığın zaman
a % b
Eğer a negatifse, olması gerektiği gibi b'ye sarmak yerine negatif bir sonuç döndürür. Bunu düzeltmenin en iyi yolu nedir? Düşünebilmemin tek yolu
a < 0 ? b + a : a % b
Yanıtlar:
Olması gerektiği gibi davranır a% b = a - a / b * b; yani geri kalan.
Yapabilirsiniz (a% b + b)% b
Bu ifade, sonucu ister pozitif ister negatif olsun , sonuçtan (a % b)daha düşük olduğu için çalışır . Ekleme negatif değerleri ilgilenir beri arasında negatif bir değerdir ve , zorunlu olarak daha düşük olduğu ve pozitif. Son modulo, başlamak için pozitif olduğu durumda oradadır , çünkü eğer pozitif ise daha büyük olur . Bu nedenle, tekrar olduğundan daha küçük hale getirir (ve negatif değerleri etkilemez ).baba(a % b)-b0(a % b + b)baa(a % b + b)b(a % b + b) % bba
(a % b)mutlaka daha düşük olduğu b(eğer olursa olsun atoplantıda olumlu veya olumsuz) bnegatif değerleri ilgilenir aberi (a % b)daha düşüktür bve daha düşük 0, (a % b + b)mutlaka daha düşük olduğu bve olumlu. Son modulo, abaşlamak için pozitif olduğu durumda oradadır , çünkü eğer apozitif (a % b + b)ise daha büyük olur b. Bu nedenle, tekrar (a % b + b) % bolduğundan bdaha küçük hale getirir (ve negatif adeğerleri etkilemez ).
a < 0belki bir göz atabilirsiniz)
(a % b + b) % bÇok büyük ave değerleri için bozulduğundan bahsetmeye değer olabilir b. Örneğin, kullanarak a = Integer.MAX_VALUE - 1ve b = Integer.MAX_VALUEverecektir -3kaçınmak istediğini olan negatif bir sayı olduğu sonucu olarak.
whilegerçekten ihtiyacınız varsa daha yavaş olacaktır, ancak yalnızca birine ihtiyacınız vardır if, bu durumda aslında daha hızlıdır.
Java 8'den itibaren Math.floorMod (int x, int y) ve Math.floorMod (long x, long y) kullanabilirsiniz . Bu yöntemlerin her ikisi de Peter'ın cevabıyla aynı sonuçları döndürür.
Math.floorMod( 2, 3) = 2
Math.floorMod(-2, 3) = 1
Math.floorMod( 2, -3) = -1
Math.floorMod(-2, -3) = -2
floatya doubleargümanlar. Mod ikili operatörü ( %) ayrıca floatve doubleişlenenlerle çalışır .
Java 8 kullanmayanlar (veya kullanamayanlar için) Guava, Guava 11.0'dan beri mevcut olan IntMath.mod () ile yardıma geldi .
IntMath.mod( 2, 3) = 2
IntMath.mod(-2, 3) = 1
Bir uyarı: Java 8'in Math.floorMod () 'unun aksine bölen (ikinci parametre) negatif olamaz.
Sayı teorisinde sonuç her zaman pozitiftir. Bilgisayar dillerinde bu her zaman geçerli değildir, çünkü tüm programcılar matematikçi değildir. Benim iki sentim, bunu dilin tasarım kusuru olarak değerlendiririm, ama şimdi değiştiremezsin.
= MOD (-4.180) = 176 = MOD (176, 180) = 176
çünkü 180 * (-1) + 176 = -4, 180 * 0 + 176 = 176 ile aynı
Buradaki saat örneğini kullanarak, http://mathworld.wolfram.com/Congruence.html , duration_of_time mod döngüsü_uzunluğu -45 dakika demezsiniz, her iki cevap da temel denklemi karşılasa bile 15 dakika diyebilirsiniz.
-1yerine seçmek n-1) sonra var.
Java 8'e sahiptir Math.floorMod, ancak çok yavaştır (uygulamasının birden çok bölümü, çarpımı ve bir koşullu vardır). JVM'nin bunun için kendine özgü optimize edilmiş bir saplamaya sahip olması mümkündür, ancak bu onu önemli ölçüde hızlandıracaktır.
Bunu olmadan yapmanın en hızlı yolu floorModburadaki diğer cevaplar gibidir, ancak koşullu dalları yoktur ve yalnızca bir yavaş %işlem vardır.
N'nin pozitif olduğunu ve x'in herhangi bir şey olabileceğini varsayarsak:
int remainder = (x % n); // may be negative if x is negative
//if remainder is negative, adds n, otherwise adds 0
return ((remainder >> 31) & n) + remainder;
Sonuçlar ne zaman n = 3:
x | result
----------
-4| 2
-3| 0
-2| 1
-1| 2
0| 0
1| 1
2| 2
3| 0
4| 1
Tam mod operatörü arasında 0ve arasında tekdüze bir dağılıma ihtiyacınız varsa n-1ve xsizinki yakınlarda kümelenmiyorsa 0, daha fazla komut seviyesi paralelliği olduğundan ve yavaş %hesaplama diğeriyle paralel olarak gerçekleşeceğinden aşağıdakiler daha da hızlı olacaktır. sonucuna bağlı olmadıkları için parçalar.
return ((x >> 31) & (n - 1)) + (x % n)
Yukarıdakiler için sonuçlar n = 3:
x | result
----------
-5| 0
-4| 1
-3| 2
-2| 0
-1| 1
0| 0
1| 1
2| 2
3| 0
4| 1
5| 2
Girdi, bir int'in tüm aralığında rastgele ise, iki çözümün dağılımı aynı olacaktır. Girdi sıfıra yakın kümelenirse n - 1, ikinci çözümde çok az sonuç olacaktır .
İşte bir alternatif:
a < 0 ? b-1 - (-a-1) % b : a % b
Bu, diğer formülden [(a% b + b)% b] daha hızlı olabilir veya olmayabilir. Diğer formülden farklı olarak, bir dal içerir, ancak bir daha az modulo işlemi kullanır. Bilgisayar <0'ı doğru tahmin edebiliyorsa, muhtemelen bir kazançtır.
(Düzenleme: Formül düzeltildi.)