İşleç Yükleme bölümünü İngilizceleştirirken şimdiki çok kötü problemlerini de çıkartmaya karar verdim:
http://ddili.org/ders/d/islec_yukleme.html
Onun yerine bir kaç gün sonra aşağıdaki problemi (ve tabii çözümünü) koyacağım. Belki kendiniz şimdiden denemek istersiniz:
Problem
Payını ve paydasını long türünde iki üye olarak tutan bir kesirli sayı türü tanımlayın. Böyle bir yapının bir yararı, float, double, ve real'deki değer kayıplarının bulunmamasıdır. Örneğin, 1.0/3 gibi bir double değerin 3 ile çarpılmasının sonucu 1.0 olmadığı halde 1⁄3'ü temsil eden Kesirli bir nesnenin 3 ile çarpılmasının sonucu tam olarak 1'dir:
struct Kesir
{
long pay;
long payda;
/* Kurucu işlev kolaylık olsun diye paydanın
* belirtilmesini gerektirmiyor ve 1 varsayıyor. */
this(long pay, long payda = 1)
{
enforce(payda != 0, "Payda sıfır olamaz");
this.pay = pay;
this.payda = payda;
/* Paydanın eksi değer almasını başından önlemek daha
* sonraki işlemleri basitleştirecek. */
if (this.payda < 0) {
this.pay = -this.pay;
this.payda = -this.payda;
}
}
/* ... işleçleri siz tanımlayın ... */
}
Bu yapı için işleçler tanımlayarak olabildiğince temel türler gibi işlemesini sağlayın. Yapının tanımı tamamlandığında aşağıdaki birim testi bloğu hatasız işletilebilsin. O blokta şu işlemler bulunuyor:
-
Payda sıfır olduğunda hata atılıyor. (Bu, yukarıdaki kurucudaki enforce ile zaten sağlanıyor.)
-
Değerin eksi işaretlisini üretmek: Örneğin, 1⁄3 değerinin eksilisi olarak -1⁄3 değeri elde ediliyor.
-
++ ve -- ile değer bir arttırılıyor veya azaltılıyor.
-
Dört işlem destekleniyor: Hem +=, -=, *=, ve /= ile tek nesnenin değeri değiştirilebiliyor hem de iki nesne +, -, *, ve / aritmetik işlemlerinde kullanılabiliyor. (Kurucuda olduğu gibi, sıfıra bölme işlemi de denetlenmeli ve önlenmelidir.)
-
Hatırlatma olarak, a⁄b ve c⁄d gibi iki kesirli arasındaki aritmetik işlem formülleri şöyledir:
** Toplama formülü: a⁄b + c⁄d = (ad + cb)⁄(bd)
** Çıkarma formülü: a⁄b - c⁄d = (ad - cb)⁄(bd)
** Çarpma formülü: a⁄b * c⁄d = (ac)⁄(bd)
** Bölme formülü: (a⁄b) / (c⁄d) = (ad)⁄(bc)
-
Nesnenin değeri gerektiğinde double'a dönüştürülebiliyor.
-
Sıralama ve eşitlik karşılaştırmaları pay ve paydaların tam değerlerine göre değil, o üyelerin ifade ettikleri değerlere göre uygulanıyorlar. Örneğin 1⁄3 ve 20⁄60 kesirli değerleri eşit kabul ediliyorlar.
unittest
{
/* Payda 0 olduğunda hata atılmalı. */
{
auto hataAtıldı_mı = false;
try {
auto b = Kesir(42, 0);
} catch (Exception hata) {
hataAtıldı_mı = true;
}
assert(hataAtıldı_mı);
}
/* 1⁄3 değeriyle başlayacağız. */
auto a = Kesir(1, 3);
/* -1⁄3 */
assert(-a == Kesir(-1, 3));
/* 1⁄3 + 1 == 4⁄3 */
++a;
assert(a == Kesir(4, 3));
/* 4⁄3 - 1 == 1⁄3 */
--a;
assert(a == Kesir(1, 3));
/* 1⁄3 + 2⁄3 == 3⁄3 */
a += Kesir(2, 3);
assert(a == Kesir(1));
/* 3⁄3 - 2⁄3 == 1⁄3 */
a -= Kesir(2, 3);
assert(a == Kesir(1, 3));
/* 1⁄3 * 8 == 8⁄3 */
a *= Kesir(8);
assert(a == Kesir(8, 3));
/* 8⁄3 / 16⁄9 == 3⁄2 */
a /= Kesir(16, 9);
assert(a == Kesir(3, 2));
/* 1.5 + 2.5 == 4 */
assert(a + Kesir(5, 2) == Kesir(4, 1));
/* 1.5 - 0.75 == 0.75 */
assert(a - Kesir(3, 4) == Kesir(3, 4));
/* 1.5 * 10 == 15 */
assert(a * Kesir(10) == Kesir(15, 1));
/* 1.5 / 4 == 3⁄8 */
assert(a / Kesir(4) == Kesir(3, 8));
/* Sıfırla bölmek hata atmalı. */
{
auto hataAtıldı_mı = false;
try {
auto sonuç = Kesir(42, 1) / Kesir(0);
} catch (Exception hata) {
hataAtıldı_mı = true;
}
assert(hataAtıldı_mı);
}
assert(to!double(a) == 1.5);
/* Payı az olan öncedir. */
assert(Kesir(3, 5) < Kesir(4, 5));
/* Paydası büyük olan öncedir. */
assert(Kesir(3, 9) < Kesir(3, 8));
assert(Kesir(1, 1_000) > Kesir(1, 10_000));
/* Değeri küçük olan öncedir. */
assert(Kesir(10, 100) < Kesir(1, 2));
/* Eksi değer öncedir. */
assert(Kesir(-1, 2) < Kesir(0));
assert(Kesir(1, -2) < Kesir(0));
/* Aynı değerler hem <= hem de >= olmalı. */
assert(Kesir(-1, -2) <= Kesir(1, 2));
assert(Kesir(1, 2) <= Kesir(-1, -2));
assert(Kesir(3, 7) <= Kesir(9, 21));
assert(Kesir(3, 7) >= Kesir(9, 21));
/* Değerleri aynı olanlar eşit olmalı. */
assert(Kesir(1, 3) == Kesir(20, 60));
/* Karışık işaretler aynı sonucu üretmeli. */
assert(Kesir(-1, 2) == Kesir(1, -2));
assert(Kesir(1, 2) == Kesir(-1, -2));
}
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]