Java, negatif sayılarla modül hesaplamalarını nasıl yapar?


97

Modülü yanlış mı yapıyorum? Çünkü Java'da -13 % 64değerlendirmek gerekiyor -13ama anlıyorum 51.


102
@Dan Statik bir ana boşluk olmasa bile ... Kodu görüyorum.
Joris Meys

22
-13 & 64 == -13 olsun
Grodriguez

7
Nasıl oluyor da -13'ten 51 oran alıyorsun?
Raedwald

3
Hiç modül yapmıyorsun. Java'da modulo operatörü yoktur. %kalan operatördür.
user207421

3
Kafa karıştırıcı soru: Java 8, bazılarının dediği gibi -13 verir. Bunu sözde hangi Java sürümüyle aldınız?
Jan Żankowski

Yanıtlar:


105

Negatif sayı modülünün her iki tanımı da kullanımdadır - bazı diller bir tanımı, diğerini kullanır.

Negatif girişler için negatif bir sayı elde etmek istiyorsanız, bunu kullanabilirsiniz:

int r = x % n;
if (r > 0 && x < 0)
{
    r -= n;
}

Aynı şekilde, negatif bir girişte negatif bir sayı döndüren bir dil kullanıyor olsaydınız ve pozitif tercih edersiniz:

int r = x % n;
if (r < 0)
{
    r += n;
}

3
N negatifse bu iyi çalışmaz. Java 7 Lang Spec (Bölüm 15.17.3) 'den aynı örneği kullanıyorsanız: (-5)% (-3) = -2. -3 eklemek işe yaramayacak. Değerin pozitif olduğundan emin olmak istiyorsanız mutlak n değerini eklemelisiniz.
partlov

6
Java'da negatif modulo hiçbir şeyi değiştirmez, yine de bir Abs () kullanırsanız, sadece r = x% abs (n) yazın. If ifadesinden hoşlanmıyorum, r = ((x% n) + n)% n yazmayı tercih ederim. 2 modulo'nun gücü (2,4,8,16 vb.) Ve olumlu yanıtla ilgili olarak, r = x & 63 ikili maskesini düşünün.
Fabyen

3
Java bağlamında (soru etiketine göre) bu cevap esasen "yanlış" tır. İfade verildiğinde x % y, A) xnegatifse geri kalan negatiftir, yani x % y == -(-x % y). B) işaretinin yetkisi yoktur, yanix % y == x % -y
Bohemian

73

"Matematiksel olarak" her ikisi de doğru olduğundan:

-13 % 64 = -13 (on modulus 64)  
-13 % 64 = 51 (on modulus 64)

Seçeneklerden birinin Java dili geliştiricileri tarafından seçilmesi gerekiyordu ve onlar şunları seçti:

sonucun işareti temettü işaretine eşittir.

Java özelliklerinde diyor ki:

https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.3


8
Soru, "Java -13 % 64 = 51bekliyordum neden bana veriyor -13?".
Pascal Cuoq

5
@pascal: java size matematikte doğru tanımı ve ondan beklediğiniz şeyi değil bunu yapmak için uygulanma şeklini verir.

9
Matematiksel olarak mantıklı davranış Java 8'de mevcuttur: Math.floorMod
Jesse Glick

1
15.17.3'lerinde bir şey . Kalan Operatör% örnekleri net değil. int result = (-5) % 3;-2 verir. int result = (-3) % 5;-3 verir. Genel olarak int result = (-a) % b;| -a | olduğunda doğru cevabı verir. > b. Doğru sonucu almak için | -a | <b böleni sarmalıyız. int result = ((-a) % b) + b;negatif a veya int result = (((-a) % b) + b) % b;pozitif veya negatif için a
Oz Edri

@Caner Bunu anlamadım, ikisi de nasıl aynı olabilir?
Kishore Kumar Korada

20

Java'da çalıştığınızdan emin misiniz? çünkü Java beklendiği gibi -13% 64 = -13 verir. Temettü işareti!


15

Java için sonucunuz yanlış. Lütfen ona nasıl ulaştığınız hakkında biraz bilgi verin (programınız, uygulamanız ve Java sürümü).

Gönderen Java Dil Şartnamede

15.17.3 Kalan Operatör%
[...]
İkili sayısal yükseltmeden (§5.6.2) sonra tamsayı olan işlenenler için kalan işlem, (a / b) * b + (a% b) 'ye eşit olacak şekilde bir sonuç değeri üretir. a.
15.17.2 Bölüm İşleci /
[...]
Tamsayı bölme 0'a doğru yuvarlanır .

/ Sıfıra yuvarlandığından (sıfırla sonuçlanır), bu durumda% sonucunun negatif olması gerekir.


15.17.3'lerinde bir şey . Kalan Operatör% örnekleri net değil. int result = (-5) % 3;-2 int result = (-3) % 5;verir -3 verir Genelde int result = (-a) % b;| -a | olduğunda doğru cevabı verir. > b | -a | olduğunda doğru sonucu almak için <b böleni sarmalıyız. int result = ((-a) % b) + b;negatif a veya int result = (((-a) % b) + b) % b;pozitif veya negatif için a.
Oz Edri

1
Yorumunuz oldukça net değil. Bölüm , doğru sonucu tanımlar ve örnekler bu tanıma uygundur. Örneğiniz için (-3) % 5tanıma göre doğru sonuçtur -3ve Java'nın doğru bir şekilde uygulanması bu sonucu vermelidir.
starblue

Sanırım kendimi doğru açıklamadım. | -A | <b olduğunda "doğru cevap" ile kastettiğim, pozitif bir sonuç elde etmek için verilen sonucu% b'ye b ekleyerek "sarmalıyız". Örneğimde, (-3)%5gerçekten verir -3ve eğer pozitif kalanı istiyorsak, buna 5 eklemeliyiz ve o zaman sonuç şöyle olacaktır2
Oz Edri

6

kullanabilirsiniz

(x % n) - (x < 0 ? n : 0);

3
@ruslik Ayrıca yapabilirsiniz: ((x % k) + k) % k. (Sizinki muhtemelen daha okunaklı olsa da)
John Kurlak

2
@JohnKurlak Sizin sürümünüz şu şekilde çalışır: 4% 3 = 1 OR 4% -3 = -2 OR -4% 3 = 2 OR -4% -3 = -1 ancak ruslik'ten gelen şu şekilde çalışır: 4% 3 = 1 VEYA% 4 -3 = 1 VEYA -4% 3 = -4 VEYA -% 4 -3 = 2
Joschua

1
@Joschua Bunu işaret ettiğiniz için teşekkürler. Benim kodum, modül sonucunun [0, sign(divisor) * divisor)yerine aralığında olmasını istediğinizde yararlıdır [0, sign(dividend) * divisor).
John Kurlak

3

Cevabınız wikipedia'da: modulo işlemi

Java'da modulo işlemindeki işaretin temettü işlemiyle aynı olduğunu söylüyor. ve bölme işleminin geri kalanından bahsettiğimiz için gayet iyi, sizin durumunuzda -13, -13/64 = 0. -13-0 = -13 olduğundan -13 döndürüyor.

DÜZENLEME: Üzgünüm, sorunuzu yanlış anladım ... Haklısınız, java -13 vermeli. Daha fazla çevre kodu sağlayabilir misiniz?


2

Negatif işlenenlerle modülo aritmetiği, onu dil gerçeklemesine bırakabilecek olan ve tanımı CPU mimarisine erteleyebilecek olan dil tasarımcısı tarafından tanımlanır.

Bir Java dili tanımı bulamadım.
Teşekkürler Ishtar, Kalan Operatör için Java Dil Spesifikasyonu % sonucun işaretinin payın işaretiyle aynı olduğunu söylüyor.


1

Bunun üstesinden gelmek 64için, pozitif olana kadar negatif değere (veya modül tabanınız ne olursa olsun) ekleyebilirsiniz.

int k = -13;
int modbase = 64;

while (k < 0) {
    k += modbase;
}

int result = k % modbase;

Sonuç yine aynı denklik sınıfında olacaktır.


1

x = x + m = x - mmodülde m.
yani -13 = -13 + 64modül 64 ve -13 = 51modül olarak 64.
Varsayalım Z = X * d + r, eğer 0 < r < Xbölünmede kalanı Z/Xçağırırsak r.
Z % Xkalanını döndürür Z/X.


1

Mod işlevi, bir sayının bölenin o sayıdan büyük olmayan en büyük tam sayı katını aştığı miktar olarak tanımlanır. Yani senin durumunda

-13 % 64

64'ün -13'ü geçmeyen en büyük tamsayı katı -64'tür. Şimdi, -64'ten -13'ü çıkardığınızda 51'e eşittir-13 - (-64) = -13 + 64 = 51


0

Java JDK 1.8.0_05 -13% 64 = -13 sürümümde

-13- (int (-13/64)) deneyebilirsiniz, başka bir deyişle, kesir kısmından kurtulmak için bir tamsayıya bölme yapın ve sonra paydan çıkarın Bu yüzden pay- (int (pay / payda)) doğru vermelidir kalan ve işaret



0

JLS'nin 15.17.3 bölümüne göre, "İkili sayısal yükseltmeden sonra tamsayı olan işlenenler için kalan işlem, (a / b) * b + (a% b) a'ya eşit olacak şekilde bir sonuç değeri üretir. Bu kimlik çift tutar özel durumda, temettü türü için olası en büyük büyüklüğe sahip negatif tamsayı ve bölen -1'dir (kalan 0'dır). "

Umarım yardımcı olur.


-1

Java'nın bu durumda 51 döndürdüğünü sanmıyorum. Mac'te Java 8 çalıştırıyorum ve şunu alıyorum:

-13 % 64 = -13

Program:

public class Test {
    public static void main(String[] args) {
        int i = -13;
        int j = 64;
        System.out.println(i % j);
    }
}

5
@XaverKapeller, hayır! Birçok insan matematiksel olarak -13 ve 51'in doğru olduğunu belirtti. Java'da -13 beklenen cevap ve bende de bu, bu yüzden gönderenin 51'i nasıl aldığını bilmiyorum, bu bir muamma. Bağlamla ilgili mod ayrıntıları bu soruyu doğru yanıtlamaya yardımcı olabilir.
Fabyen

@Xaver Kapeller: 51 ve -13'ün ikisi de nasıl doğru olabilir? Java yalnızca bir değer döndürür ..
ceprateek

@XaverKapeller Java'nın aslında yanlış olabileceğini belgeleyen bir cevap nasıl olabilir?
user207421

@EJP 3 yıl önce bunu yazdığımda, java'nın bununla nasıl başa çıktığının basit gerçekliğinden çok matematiksel doğruluğa değer verecek kadar aptal olduğumu düşünüyorum. Aptal
yorumumu
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.