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 | Örnek | Sonuç |
|---|---|---|---|
+ | Toplama | 5 + 3 | 8 |
- | Çıkarma | 5 - 3 | 2 |
* | Çarpma | 5 * 3 | 15 |
/ | Bölme | 5 / 3 | 1 (!) |
% | Mod (kalan) | 5 % 3 | 2 |
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)); // 1Bunlar 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ĞRUMod 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); // 3Yaygı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:05Negatif 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); // -1Bu 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=6Farkı 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); // 11Tek 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 anlarAtama Operatörleri
Kısayol atama operatörleri işlemi yapıp sonucu aynı değişkene atar:
| Operatör | Karşılığı | Örnek |
|---|---|---|
+= | a = a + b | a += 5 |
-= | a = a - b | a -= 3 |
*= | a = a * b | a *= 2 |
/= | a = a / b | a /= 4 |
%= | a = a % b | a %= 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); // 2Bu 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 yaparb + 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.
| Öncelik | Operatö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 → doublePromosyon kuralları sırasıyla:
byte,short,char→int(her zaman)Bir operand
long→ diğerilongBir operand
float→ diğerifloatBir operand
double→ diğeridouble
// 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.0Overflow — 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 zeroAma 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)); // trueNaN ö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ırOndalı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); // truePara 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
doublekullanma.BigDecimalkullan. İ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 → floorfloorMod() 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.3333Pratik Ö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ĞRUKural 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ı):
| Öncelik | Operatör | Yö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); // -5Pratik Ö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.02. 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 BigInteger3. 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 yol5. 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
intbölündüğünde sonuçint'tir — ondalık kısım kesilir. Ondalık sonuç için en az bir operandıdoubleyapMod 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 kullanmaAtama operatörleri (
+=,-=vb.) implicit cast yapar —byteveshortile çalışırken faydalıOverflow sessiz gerçekleşir — Java hata vermez, çöp değer verir.
Math.addExact()ile korunBigInteger ve BigDecimal ile primitive sınırlarını aşabilirsin — para hesaplamalarında
BigDecimalzorunluOndalıklı sayı karşılaştırmasında
==kullanma — epsilon ile karşılaştır veyaBigDecimalkullan
AI Asistan
Sorularını yanıtlamaya hazır