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 ).b
a
b
a
(a % b)
-b
0
(a % b + b)
b
a
a
(a % b + b)
b
(a % b + b) % b
b
a
(a % b)
mutlaka daha düşük olduğu b
(eğer olursa olsun a
toplantıda olumlu veya olumsuz) b
negatif değerleri ilgilenir a
beri (a % b)
daha düşüktür b
ve daha düşük 0
, (a % b + b)
mutlaka daha düşük olduğu b
ve olumlu. Son modulo, a
başlamak için pozitif olduğu durumda oradadır , çünkü eğer a
pozitif (a % b + b)
ise daha büyük olur b
. Bu nedenle, tekrar (a % b + b) % b
olduğundan b
daha küçük hale getirir (ve negatif a
değerleri etkilemez ).
a < 0
belki bir göz atabilirsiniz)
(a % b + b) % b
Çok büyük a
ve değerleri için bozulduğundan bahsetmeye değer olabilir b
. Örneğin, kullanarak a = Integer.MAX_VALUE - 1
ve b = Integer.MAX_VALUE
verecektir -3
kaçınmak istediğini olan negatif bir sayı olduğu sonucu olarak.
while
gerç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
float
ya double
argümanlar. Mod ikili operatörü ( %
) ayrıca float
ve double
iş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.
-1
yerine 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 floorMod
buradaki 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 0
ve arasında tekdüze bir dağılıma ihtiyacınız varsa n-1
ve x
sizinki 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.)