← Kursa Dön
📄 Text · 12 min

Aritmetik Operatörler

Programlama sonuçta sayılarla iş yapmak. Toplama, çıkarma, çarpma, bölme — matematik dersinden tanıdık operatörler ama Java'da birkaç tuzak var. Özellikle tam sayı bölmesi ve taşma (overflow) konuları dikkat ister.


Temel Aritmetik Operatörler

OperatörİşlemÖrnekSonuç
+Toplama5 + 38
-Çıkarma5 - 32
*Çarpma5 * 315
/Bölme5 / 31 (!)
%Mod (kalan)5 % 32
int a = 10;
int b = 3;

System.out.println("Toplam:  " + (a + b)); // 13
System.out.println("Fark:    " + (a - b)); // 7
System.out.println("Çarpım:  " + (a * b)); // 30
System.out.println("Bölüm:   " + (a / b)); // 3 (tam sayı!)
System.out.println("Kalan:   " + (a % b)); // 1

Bunlar basit görünüyor ama şeytan detaylarda gizli. Her birinin incelikleri var ve bu incelikleri bilmek seni pek çok bug'dan kurtarır. Özellikle bölme ve mod operatörlerinde dikkat et.


Integer Division Tuzağı — Tam Sayı Bölmesi

Java'da iki int bölündüğünde sonuç da int olur. Ondalık kısım atılır — yuvarlanmaz, atılır.

int a = 7;
int b = 2;
int sonuc = a / b;
System.out.println(sonuc); // 3 — 3.5 değil!

Bunu şöyle düşün: Bir pastayı 2 kişiye bölüyorsun. Her birine 3 dilim düşüyor, yarım dilimi çöpe atıyorsun. Java acımasız, yuvarlamaz bile.

System.out.println(10 / 3);  // 3
System.out.println(10 / 4);  // 2
System.out.println(1 / 2);   // 0 (!)
System.out.println(-7 / 2);  // -3 (sıfıra doğru keser)

Ondalıklı Sonuç Nasıl Alınır?

En az bir operandı double veya float yapmalısın:

// Yol 1: Literal olarak yaz
System.out.println(10.0 / 3);   // 3.3333...
System.out.println(10 / 3.0);   // 3.3333...

// Yol 2: Cast kullan
int x = 10;
int y = 3;
double sonuc = (double) x / y;
System.out.println(sonuc);       // 3.3333...

// Yanlış! Önce bölme yapılır, sonra cast
double yanlis = (double) (x / y);
System.out.println(yanlis);      // 3.0 — çok geç!

⚠️ Dikkat: (double)(x / y) yazarsan önce int bölme yapılır (sonuç 3), sonra 3 double'a çevrilir (3.0). Cast'ı bölmeden önce yapmalısın.

// Ortalama hesaplama — klasik hata
int toplam = 17;
int adet = 5;

double ortalama1 = toplam / adet;          // 3.0 — YANLIŞ
double ortalama2 = (double) toplam / adet;  // 3.4 — DOĞRU

Mod Operatörü (%)

Bölme işleminin kalanını verir. Çok kullanışlı bir operatör.

System.out.println(10 % 3); // 1 (10 = 3*3 + 1)
System.out.println(10 % 2); // 0 (10 çift sayı)
System.out.println(10 % 5); // 0 (tam bölünür)
System.out.println(7 % 4);  // 3

Yaygın Kullanım Alanları

// Çift/tek kontrolü
int sayi = 42;
if (sayi % 2 == 0) {
    System.out.println("Çift sayı");
} else {
    System.out.println("Tek sayı");
}

// Döngüsel indeks (0, 1, 2, 0, 1, 2, ...)
for (int i = 0; i < 10; i++) {
    int indeks = i % 3;
    System.out.print(indeks + " ");
}
// 0 1 2 0 1 2 0 1 2 0
// Zaman dönüşümü
int toplamSaniye = 3725;
int saat = toplamSaniye / 3600;          // 1
int dakika = (toplamSaniye % 3600) / 60; // 2
int saniye = toplamSaniye % 60;          // 5
System.out.printf("%d:%02d:%02d%n", saat, dakika, saniye); // 1:02:05

Negatif Sayılarda Mod

Java'da mod operatörünün işareti sol operanda bağlıdır:

System.out.println(7 % 3);    //  1
System.out.println(-7 % 3);   // -1
System.out.println(7 % -3);   //  1
System.out.println(-7 % -3);  // -1

Bu matematikteki mod tanımından farklı olabilir. Dikkatli ol.


Artırma ve Azaltma: ++ ve --

++ bir artırır, -- bir azaltır. İki kullanım şekli var:

int x = 5;

// Prefix (ön ek): önce artır, sonra kullan
int a = ++x; // x=6, a=6

// Postfix (son ek): önce kullan, sonra artır
int y = 5;
int b = y++; // b=5, y=6

Farkı görelim:

int i = 10;
System.out.println(++i); // 11 (önce artır, sonra yazdır)
System.out.println(i);   // 11

int j = 10;
System.out.println(j++); // 10 (önce yazdır, sonra artır)
System.out.println(j);   // 11

Tek başına kullanıldığında fark yok:

int k = 5;
k++;  // k = 6
++k;  // k = 7
// İkisi de aynı sonucu verir

💡 Tavsiye: ++ ve -- operatörlerini karmaşık ifadelerin içinde kullanma. Okunabilirliği düşürür ve hata riski artar. Tek başına bir satırda kullan.

// Kötü — ne oluyor anlamak zor
int a = 5;
int b = a++ + ++a; // b = ? (Cevap: 12, ama bunu kim anlar?)

// İyi — açık ve net
int a = 5;
a++;
int b = a + a; // Herkes anlar

Atama Operatörleri

Kısayol atama operatörleri işlemi yapıp sonucu aynı değişkene atar:

OperatörKarşılığıÖrnek
+=a = a + ba += 5
-=a = a - ba -= 3
*=a = a * ba *= 2
/=a = a / ba /= 4
%=a = a % ba %= 3
int puan = 100;
puan += 20;  // puan = 120
puan -= 50;  // puan = 70
puan *= 2;   // puan = 140
puan /= 7;   // puan = 20
puan %= 3;   // puan = 2

System.out.println(puan); // 2

Bu operatörler sadece kısayol değil, bir de gizli cast yapar:

byte b = 10;
// b = b + 5;   // HATA! b + 5 int döner, byte'a sığmaz
b += 5;          // OK! += implicit cast yapar

b + 5 ifadesi int sonuç üretir (Java'da byte ve short aritmetikte int'e yükseltilir). b = b + 5 yazarsan int'i byte'a atamazsın, cast gerekir. Ama b += 5 otomatik cast yapar — bu bir Java inceliği.


Operatör Önceliği

Matematik kuralları geçerli: çarpma/bölme toplamadan önce yapılır.

ÖncelikOperatörler
1 (en yüksek)++, -- (prefix), +, - (tekli)
2*, /, %
3+, -
4 (en düşük)=, +=, -=, *=, /=, %=
int sonuc = 2 + 3 * 4;     // 14 (3*4=12, 2+12=14)
int sonuc2 = (2 + 3) * 4;  // 20 (parantez önce)

System.out.println(10 + 6 / 3);   // 12 (6/3=2, 10+2=12)
System.out.println((10 + 6) / 3); // 5

⚠️ Kuralı hatırlayamıyorsan parantez koy. Parantez hem doğruluğu garanti eder hem okunabilirliği artırır. Kimse kodunda matematik bilgisi yarıştırmıyor.


Aritmetik İfadelerde Tip Promosyonu

Farklı tipler bir arada kullanıldığında Java otomatik olarak küçük tipi büyüğe çevirir:

byte a = 10;
byte b = 20;
// byte c = a + b; // HATA! Sonuç int
int c = a + b;     // OK

short s = 100;
int i = 200;
// İfadenin tipi: int + int = int (short otomatik int olur)
int toplam = s + i;

// float ve double karışırsa → double
float f = 3.14f;
double d = 2.0;
double sonuc = f + d; // float → double

Promosyon kuralları sırasıyla:

  1. byte, short, charint (her zaman)

  2. Bir operand long → diğeri long

  3. Bir operand float → diğeri float

  4. Bir operand double → diğeri double

// Karışık tip örneği
byte b = 10;
long l = 100L;
float f = 3.0f;
double d = 2.0;

// b + l → long (byte→int→long)
// (b + l) + f → float (long→float)
// ((b + l) + f) + d → double (float→double)
var sonuc = b + l + f + d; // double
System.out.println(sonuc); // 115.0

Overflow — Taşma

Her sayısal tipin bir aralığı var. Bu aralığı aşarsan "overflow" (taşma) olur ve Java hata vermez — sessizce yanlış sonuç verir.

int max = Integer.MAX_VALUE; // 2,147,483,647
System.out.println(max);     // 2147483647
System.out.println(max + 1); // -2147483648 (!)

Bunu bir arabanın kilometre sayacı gibi düşün: 999,999 km'den sonra 000,000'a dönmesi gibi. Tam sayılar da "döner".

// Overflow örnekleri
byte b = 127;
b++;
System.out.println(b); // -128

int big = 1000000;
int sonuc = big * big; // 1,000,000,000,000 → int'e sığmaz!
System.out.println(sonuc); // -727379968 (çöp değer)

Overflow'dan Korunma

// Yol 1: Daha büyük tip kullan
long big = 1000000L;
long sonuc = big * big;
System.out.println(sonuc); // 1000000000000 — doğru

// Yol 2: Math.addExact() — taşma olursa exception fırlatır
try {
    int sonuc2 = Math.addExact(Integer.MAX_VALUE, 1);
} catch (ArithmeticException e) {
    System.out.println("Taşma oldu!"); // Bu çalışır
}

// Yol 3: Kontrol et
int a = 2000000000;
int b = 1000000000;
if ((long) a + b > Integer.MAX_VALUE) {
    System.out.println("Taşma riski var!");
}

Java 8+ ile gelen Math.addExact(), Math.subtractExact(), Math.multiplyExact() metotları taşma durumunda ArithmeticException fırlatır. Güvenli hesaplama istiyorsan bunları kullan.


Sıfıra Bölme

Tam sayılarda sıfıra bölme ArithmeticException fırlatır:

// int bölme — HATA!
int a = 10;
int b = 0;
// int sonuc = a / b; // ArithmeticException: / by zero

Ama double'da sıfıra bölme hata vermez — özel değerler döner:

double x = 10.0 / 0.0;
System.out.println(x); // Infinity

double y = -10.0 / 0.0;
System.out.println(y); // -Infinity

double z = 0.0 / 0.0;
System.out.println(z); // NaN (Not a Number)

System.out.println(Double.isInfinite(x)); // true
System.out.println(Double.isNaN(z));       // true

NaN özel bir değer — kendisiyle bile eşit değildir:

double nan = Double.NaN;
System.out.println(nan == nan); // false (!)
System.out.println(Double.isNaN(nan)); // true — kontrol böyle yapılır

Ondalıklı Sayı Aritmetiği — Hassasiyet Sorunu

System.out.println(0.1 + 0.2);         // 0.30000000000000004
System.out.println(0.1 + 0.2 == 0.3);  // false (!)

Bu Java'nın hatası değil — IEEE 754 floating point standardının doğası. Bilgisayar 0.1'i ikili sistemde tam olarak ifade edemez, tıpkı 1/3'ü ondalık sistemde tam yazamayışımız gibi (0.3333...).

Ondalıklı Sayıları Nasıl Karşılaştırmalı?

double a = 0.1 + 0.2;
double b = 0.3;

// Kötü
System.out.println(a == b); // false

// İyi — epsilon ile karşılaştır
double epsilon = 1e-10;
System.out.println(Math.abs(a - b) < epsilon); // true

Para Hesaplamalarında BigDecimal

import java.math.BigDecimal;

BigDecimal fiyat = new BigDecimal("19.99");
BigDecimal adet = new BigDecimal("3");
BigDecimal toplam = fiyat.multiply(adet);

System.out.println(toplam); // 59.97 — tam doğru!

💡 Para, finansal hesaplamalar ve hassas ondalıklı işlemler için double kullanma. BigDecimal kullan. İlerideki derslerde detaylı göreceğiz.


Math Sınıfı — Matematik Yardımcıları

Java'nın Math sınıfı sık kullanılan matematik fonksiyonlarını sunar:

// Temel işlemler
System.out.println(Math.abs(-5));       // 5 (mutlak değer)
System.out.println(Math.max(10, 20));   // 20
System.out.println(Math.min(10, 20));   // 10
System.out.println(Math.pow(2, 10));    // 1024.0 (üs)
System.out.println(Math.sqrt(144));     // 12.0 (karekök)

// Yuvarlama
System.out.println(Math.round(3.7));    // 4 (en yakına)
System.out.println(Math.round(3.5));    // 4 (yarıyı yukarı)
System.out.println(Math.ceil(3.1));     // 4.0 (yukarı)
System.out.println(Math.floor(3.9));    // 3.0 (aşağı)

// Rastgele sayı
System.out.println(Math.random());      // 0.0-1.0 arası

// Belirli aralıkta rastgele (1-100)
int rastgele = (int)(Math.random() * 100) + 1;
System.out.println("Rastgele (1-100): " + rastgele);

Math.floorDiv() ve Math.floorMod()

Java 8+ ile gelen bu metotlar negatif sayılarda daha "matematiksel" davranır:

// Normal bölme — sıfıra doğru keser
System.out.println(-7 / 2);            // -3
System.out.println(-7 % 2);            // -1

// floorDiv — aşağıya yuvarlar
System.out.println(Math.floorDiv(-7, 2)); // -4
System.out.println(Math.floorMod(-7, 2)); // 1

// Fark: -7 = (-3)*2 + (-1) → normal
//        -7 = (-4)*2 + 1   → floor

floorMod() her zaman pozitif sonuç verir (bölen pozitifse), bu da döngüsel hesaplamalarda çok kullanışlı:

// Saat hesaplama: 3 saat geri git
int saat = 2;
int geriGit = 3;
int yeniSaat = Math.floorMod(saat - geriGit, 24); // 23 (02:00 - 3 saat = 23:00)
System.out.println(yeniSaat); // 23

// Normal mod ile: (2 - 3) % 24 = -1 (yanlış!)

Büyük Sayı İşlemleri: BigInteger ve BigDecimal

Primitive tiplerin sınırları yetmediğinde BigInteger ve BigDecimal devreye girer:

import java.math.BigInteger;
import java.math.BigDecimal;
import java.math.RoundingMode;

// BigInteger — sınırsız tam sayı
BigInteger a = new BigInteger("99999999999999999999999999999");
BigInteger b = new BigInteger("88888888888888888888888888888");
BigInteger toplam = a.add(b);
System.out.println(toplam); // 188888888888888888888888888887

BigInteger carpim = a.multiply(b);
System.out.println(carpim); // Devasa bir sayı

// Faktöriyel hesaplama
BigInteger faktoriyel = BigInteger.ONE;
for (int i = 2; i <= 50; i++) {
    faktoriyel = faktoriyel.multiply(BigInteger.valueOf(i));
}
System.out.println("50! = " + faktoriyel);
// 30414093201713378043612608166979581188299763898377...

// BigDecimal — hassas ondalıklı
BigDecimal fiyat = new BigDecimal("19.99");
BigDecimal adet = new BigDecimal("3");
BigDecimal toplam2 = fiyat.multiply(adet);
System.out.println(toplam2); // 59.97 — tam doğru!

// Bölme — scale ve rounding belirtmek zorunlu
BigDecimal bolum = new BigDecimal("10")
    .divide(new BigDecimal("3"), 4, RoundingMode.HALF_UP);
System.out.println(bolum); // 3.3333

Pratik Örnek: Sıcaklık Dönüştürücü

public class SicaklikDonusturucu {
    public static void main(String[] args) {
        double celsius = 36.6;
        
        // Celsius → Fahrenheit: F = C * 9/5 + 32
        double fahrenheit = celsius * 9.0 / 5.0 + 32;
        
        // Celsius → Kelvin: K = C + 273.15
        double kelvin = celsius + 273.15;
        
        System.out.printf("%.1f°C = %.1f°F = %.2fK%n", 
            celsius, fahrenheit, kelvin);
        // 36.6°C = 97.9°F = 309.75K
        
        // Integer division tuzağı!
        double yanlis = celsius * 9 / 5 + 32; // 9/5=1! (int bölme)
        // Aslında burada 9 ve 5 int, ama celsius double 
        // olduğu için 9 önce double'a çevrilir — sorun yok.
        // Ama şu olsaydı:
        int c = 37;
        double f = c * 9 / 5 + 32; // 9/5=1! Çünkü hepsi int
        System.out.println(f); // 69.0 — YANLIŞ! (doğrusu 98.6)
        
        double fDogru = c * 9.0 / 5 + 32;
        System.out.println(fDogru); // 98.6 — DOĞRU
    }
}

Aritmetik İşlemlerde String Birleştirme Tuzağı

+ operatörü hem toplama hem String birleştirme yapar. Bu karışıklığa yol açabilir:

System.out.println(1 + 2 + "3");    // "33" — önce 1+2=3, sonra "3"+"3"
System.out.println("1" + 2 + 3);    // "123" — "1"+2="12", "12"+3="123"
System.out.println("1" + (2 + 3));  // "15" — parantez içi önce: 2+3=5

int a = 5, b = 10;
System.out.println("Toplam: " + a + b);     // "Toplam: 510" — YANLIŞ!
System.out.println("Toplam: " + (a + b));   // "Toplam: 15" — DOĞRU

Kural basit: soldan sağa işlenir. Bir tarafta String varsa + birleştirme yapar, ikisi de sayıysa toplama yapar.


Unary Operatörler

Tek operandla çalışan operatörler:

int a = 5;

// Pozitif/Negatif
int b = -a;  // -5
int c = +a;  // 5 (genellikle gereksiz ama geçerli)

// Artırma/Azaltma (tekrar)
int d = ++a; // a=6, d=6
int e = a--; // e=6, a=5

// Boolean negation
boolean x = true;
boolean y = !x; // false

İşlem Sırası Detayları

Karmaşık ifadelerde Java'nın hangi sırayla işlem yaptığını bilmek önemli. İşte tam öncelik tablosu (aritmetik kısmı):

ÖncelikOperatörYön
1() parantez
2++x, --x, +x, -x (prefix/unary)Sağdan sola
3*, /, %Soldan sağa
4+, -Soldan sağa
5=, +=, -=, *=, /=, %=Sağdan sola
// Adım adım analiz
int sonuc = 2 + 3 * 4 - 6 / 2;
// Adım 1: 3 * 4 = 12
// Adım 2: 6 / 2 = 3
// Adım 3: 2 + 12 = 14
// Adım 4: 14 - 3 = 11
System.out.println(sonuc); // 11

// Parantezle değiştir
int sonuc2 = (2 + 3) * (4 - 6) / 2;
// Adım 1: (2 + 3) = 5
// Adım 2: (4 - 6) = -2
// Adım 3: 5 * (-2) = -10
// Adım 4: -10 / 2 = -5
System.out.println(sonuc2); // -5

Pratik Örnek: KDV Hesaplayıcı

public class KdvHesaplayici {
    public static void main(String[] args) {
        double urunFiyat = 1500.0;
        double kdvOrani = 0.20; // %20
        
        double kdvTutari = urunFiyat * kdvOrani;
        double toplamFiyat = urunFiyat + kdvTutari;
        
        System.out.printf("Ürün fiyatı : %.2f TL%n", urunFiyat);
        System.out.printf("KDV (%%20)   : %.2f TL%n", kdvTutari);
        System.out.printf("Toplam fiyat: %.2f TL%n", toplamFiyat);
        
        // İndirimli hesaplama
        double indirimYuzdesi = 15; // %15
        double indirimliFiyat = toplamFiyat * (1 - indirimYuzdesi / 100);
        System.out.printf("İndirimli   : %.2f TL%n", indirimliFiyat);
        
        // Taksit hesaplama
        int taksitSayisi = 6;
        double taksitTutari = indirimliFiyat / taksitSayisi;
        System.out.printf("Aylık taksit (%d ay): %.2f TL%n", 
            taksitSayisi, taksitTutari);
    }
}

Pratik Örnek: Zaman Hesaplama

public class ZamanHesaplama {
    public static void main(String[] args) {
        int toplamSaniye = 86399; // 23:59:59
        
        int saat = toplamSaniye / 3600;
        int kalanSaniye = toplamSaniye % 3600;
        int dakika = kalanSaniye / 60;
        int saniye = kalanSaniye % 60;
        
        System.out.printf("%02d:%02d:%02d%n", saat, dakika, saniye);
        // 23:59:59
        
        // Gün hesaplama
        int toplamDakika = 14567;
        int gun = toplamDakika / (60 * 24);
        int kalanDk = toplamDakika % (60 * 24);
        int s = kalanDk / 60;
        int dk = kalanDk % 60;
        
        System.out.printf("%d gün, %d saat, %d dakika%n", gun, s, dk);
        // 10 gün, 2 saat, 47 dakika
    }
}

Sık Yapılan Hatalar

1. Integer division:

double oran = 1 / 3; // 0.0 — iki int bölünür!
double oran2 = 1.0 / 3; // 0.333... — doğru

// Yüzde hesaplama tuzağı
int basarili = 7;
int toplam = 10;
double yuzde = basarili / toplam * 100; // 0.0!
double dogruYuzde = (double) basarili / toplam * 100; // 70.0

2. Overflow kontrolü yapmamak:

int fiyat = 2000000000;
int kdv = (int)(fiyat * 1.18); // Overflow! Negatif sayı çıkar
long kdvDogru = (long) fiyat * 118 / 100; // Güvenli

// Faktöriyel hesaplamada overflow
int faktoriyel = 1;
for (int i = 1; i <= 20; i++) {
    faktoriyel *= i; // 13!'den itibaren overflow!
}
// long kullan, hatta 20!'den fazlası için BigInteger

3. String + ile aritmetik karışımı:

System.out.println("Sonuç: " + 3 + 4);   // "Sonuç: 34"
System.out.println("Sonuç: " + (3 + 4)); // "Sonuç: 7"
System.out.println(3 + 4 + " Sonuç");    // "7 Sonuç"

4. NaN karşılaştırması:

double x = 0.0 / 0.0;
if (x == Double.NaN) { } // Her zaman false!
if (Double.isNaN(x)) { } // Doğru yol

5. Mod ile negatif sayı:

// Dizide döngüsel indeks
int indeks = -1 % 5; // -1 (0-4 arası değil!)
// Güvenli mod:
int guvenli = (((-1 % 5) + 5) % 5); // 4

Özet

  • Java'da iki int bölündüğünde sonuç int'tir — ondalık kısım kesilir. Ondalık sonuç için en az bir operandı double yap

  • Mod operatörü (%) kalan hesaplar — çift/tek kontrolü, döngüsel indeks gibi işlerde çok kullanılır

  • ++/-- prefix ve postfix farkına dikkat et; karmaşık ifadelerde kullanma

  • Atama operatörleri (+=, -= vb.) implicit cast yapar — byte ve short ile çalışırken faydalı

  • Overflow sessiz gerçekleşir — Java hata vermez, çöp değer verir. Math.addExact() ile korun

  • BigInteger ve BigDecimal ile primitive sınırlarını aşabilirsin — para hesaplamalarında BigDecimal zorunlu

  • Ondalıklı sayı karşılaştırmasında == kullanma — epsilon ile karşılaştır veya BigDecimal kullan