Ders 03 / 11
Mantıksal İşlevler
Aynı iç içe koşul 10/25/40 m³ tarife basamaklarına üç yazımla uygulanıyor: sınır karşılaştırması `<=` yerine `<` olunca 4 kayıt basamak değiştiriyor, koşulların sırası bozulunca 20 kayıt yanlış basamağa düşüyor ve birinci basamak tamamen boşalıyor. Sınır kararı tutar toplamını 26 219,52'den 26 698,32 ücret birimine, yani yüzde 1,83 oynatıyor, ama tek bir faturayı yüzde 35,5 oynatıyor. Aynı toplamı üreten üç yazımdan yalnız birinde basamak bir hücreye yazılı; ötekilerde karar 3 katmanlı bir koşulun içinde ve hiçbir hücrede durmuyor.
İçindekiler
Önceki ders bir aralığın kaç hücresinin sayıldığını ölçtü ve her sayımda tek bir eşik kullandı. Tarife tek eşikli değildir: bir kaydın hangi basamağa düştüğü 10, 25 ve 40 m³ sınırlarına sırayla bakan iç içe bir koşulla belirlenir. Her katmanda bir karşılaştırma işareti ve bir sıra seçilir; ikisi de yazan kişinin kararıdır ve sayfada görünmez.
Bu ders aynı 60 kaydı üç ayrı iç içe koşulla basamaklara dağıtır, ardından basamağı tutara çevirir. Sınırda duran kayıt azdır, ama karşılaştırma işaretinin bütün ağırlığını onlar taşır.
- TT10. Tarife faturalanan tüketime uygulanır ve faturalanan tüketim tam m³’e yuvarlanır. Yuvarlama bir karardır; sınıra tam oturan kayıtları yaratan da odur.
- TT11. Tarife tablosu sayfada durur:
Jbasamak numarası,Küst sınır,Lbirim ücret çarpanı. Sınırlar ve çarpanlar kurgudur. Aynı sınır sayıları önceki derslerin parametre bloğunda da bulunur; bu tekrarın bedeli aşağıda ölçülür. - TT12.
egerişlevi koşulu değerlendirir ve iki daldan birini döndürür. İç içe yazıldığında koşullar soldan sağa denenir ve ilk tutan dal kazanır. Sıra bu yüzden bir karardır.
Sınıra Tam Oturan Kayıtlar
Aşağıdaki blok sayfayı kurar. Üretici önceki derslerdeki sırayla çağrılır; yeni olan F sütunu
ile tarife tablosudur.
// tarife.mjs — elektronik tablo MODELI: 01'in modeli, mantiksal islevlerle genisletilmis. // Tarife tablosu sayfada durur; basamak sinirlari ve carpanlar hucrelerden okunur. export const TOHUM = 20260602, SATIR = 60; const uretec = (t) => { let s = t >>> 0; return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; }; const REF = /(\$?)([A-Z])(\$?)(\d+)/g; export const kaydir = (f, dS, dR) => f.replace(REF, (_, a, s, b, r) => (a ? "$" + s : String.fromCharCode(s.charCodeAt(0) + dS)) + (b ? "$" + r : String(+r + dR))); // Bu dersin formullerinde aralik yok; model yalniz hucre basvurusu ve islev cagrisi cozer. const ISLEV = { eger: (k, d, y) => (k ? d : y), // kosul once degerlendirilir, ilk tutan dal kazanir yuvarla: (x) => Math.round(x), enk: (a, b) => Math.min(a, b), enb: (a, b) => Math.max(a, b), }; export function deger(H, ad) { const v = H[ad]; if (v === undefined) return 0; if (typeof v !== "string" || v[0] !== "=") return v; const ifade = v.slice(1).replace(REF, (m) => JSON.stringify(deger(H, m.replace(/\$/g, "")))); return Function(...Object.keys(ISLEV), `return (${ifade});`)(...Object.values(ISLEV)); } export function sayfa() { const r = uretec(TOHUM), H = {}; H.A1 = "abone"; H.C1 = "tuketim"; H.F1 = "faturalanan"; for (let i = 0; i < SATIR; i++) { const s = i + 2; H["A" + s] = "AB-" + String(1041 + i * 7).padStart(4, "0"); r(); // 01'deki bolge sutunu: uretec ayni sirada calisir H["C" + s] = Math.round((2 + r() * r() * 78) * 10) / 10; H["F" + s] = "=yuvarla(C" + s + ")"; // faturalanan tuketim tam m3'e yuvarlanir } // 01'deki parametre blogu aynen durur: birim ucret H2, sabit bedel H3, sinirlar H6:H8. ["birim ucret", "sabit bedel", "sayac bakim", "kayip payi", "basamak 1", "basamak 2", "basamak 3", "indirim"].forEach((e, j) => { H["G" + (j + 2)] = e; }); [8.4, 25, 3.5, 1.2, 10, 25, 40, 0.9].forEach((v, j) => { H["H" + (j + 2)] = v; }); // Tarife tablosu: J basamak, K ust sinir (m3), L birim ucret carpani. H.J1 = "basamak"; H.K1 = "ust sinir"; H.L1 = "carpan"; [1, 2, 3, 4].forEach((b, j) => { H["J" + (j + 2)] = b; }); [10, 25, 40, ""].forEach((k, j) => { H["K" + (j + 2)] = k; }); [1, 1.4, 1.9, 2.6].forEach((c, j) => { H["L" + (j + 2)] = c; }); return H; } if (import.meta.url === `file://${process.argv[1]}`) { const H = sayfa(); const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); const y = g([8, 10, 12, 14]); console.log(y(["hucre", "tuketim", "faturalanan", "sinirda mi"])); const F = Array.from({ length: SATIR }, (_, i) => deger(H, "F" + (i + 2))); const SINIR = [10, 25, 40]; for (const s of [2, 3, 30, 36, 45, 61]) console.log(y(["F" + s, H["C" + s].toFixed(1), deger(H, "F" + s), SINIR.includes(deger(H, "F" + s)) ? "evet" : "hayir"])); const n = (f) => F.filter(f).length; console.log(`\nFaturalanan tuketim dagilimi — 1. basamak ${n((v) => v <= 10)}, ` + `2. basamak ${n((v) => v > 10 && v <= 25)}, 3. basamak ${n((v) => v > 25 && v <= 40)}, ` + `4. basamak ${n((v) => v > 40)}`); console.log(`Sinira tam oturan kayit: ` + SINIR.map((v) => `${v} m3: ${n((x) => x === v)}`).join(", ") + ` — toplam ${n((v) => SINIR.includes(v))}`); }
hucre tuketim faturalanan sinirda mi F2 9.8 10 evet F3 71.6 72 hayir F30 25.4 25 evet F36 25.0 25 evet F45 39.9 40 evet F61 21.2 21 hayir Faturalanan tuketim dagilimi — 1. basamak 20, 2. basamak 18, 3. basamak 9, 4. basamak 13 Sinira tam oturan kayit: 10 m3: 1, 25 m3: 2, 40 m3: 1 — toplam 4
Dört kayıt sınıra tam oturuyor ve dördü oraya farklı yoldan geldi: F2 yukarı yuvarlandı,
F30 aşağı, F36 zaten 25’ti, F45 yukarı. Yuvarlama olmasaydı hiçbiri sınırda olmayacaktı;
bir sınır sorusunu yaratan şey, sınırla ilgisi olmayan bir başka karardır.
Aynı Koşul, Üç Yazım
Basamak numarası üç iç içe eger ile atanır. Birincisi sınırı dahil eder, ikincisi etmez,
üçüncüsü eder ama koşulları yanlış sırada dener.
// basamak.mjs — ayni ic ice kosul uc yazimla: <=, < ve sirasi bozulmus hali. import { sayfa, deger, kaydir, SATIR } from "./tarife.mjs"; const KOSUL = { A: "=eger(F2<=$K$2,$J$2,eger(F2<=$K$3,$J$3,eger(F2<=$K$4,$J$4,$J$5)))", B: "=eger(F2<$K$2,$J$2,eger(F2<$K$3,$J$3,eger(F2<$K$4,$J$4,$J$5)))", C: "=eger(F2<=$K$3,$J$3,eger(F2<=$K$2,$J$2,eger(F2<=$K$4,$J$4,$J$5)))", }; const H = sayfa(); const sutun = (f) => { const K = { ...H }; for (let i = 0; i < SATIR; i++) K["M" + (i + 2)] = kaydir(f, 0, i); return Array.from({ length: SATIR }, (_, i) => deger(K, "M" + (i + 2))); }; const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); const D = Object.fromEntries(Object.entries(KOSUL).map(([a, f]) => [a, sutun(f)])); const y = g([8, 12, 8, 8, 12]); console.log(y(["hucre", "faturalanan", "A <=", "B <", "C sirasiz"])); for (const s of [2, 3, 30, 36, 45, 61]) { const i = s - 2; console.log(y(["M" + s, deger(H, "F" + s), D.A[i], D.B[i], D.C[i]])); } const z = g([12, 10, 10, 10, 10, 14]); console.log("\n" + z(["yazim", "1. bas.", "2. bas.", "3. bas.", "4. bas.", "A'dan farkli"])); for (const [a, s] of Object.entries(D)) console.log(z([a, ...[1, 2, 3, 4].map((b) => s.filter((v) => v === b).length), s.filter((v, i) => v !== D.A[i]).length])); console.log(`\nIc ice kosul derinligi ${(KOSUL.A.match(/eger\(/g) ?? []).length}; ` + `sinirlar K2:K4 hucrelerinden okunuyor.`);
hucre faturalanan A <= B < C sirasiz M2 10 1 2 2 M3 72 4 4 4 M30 25 2 3 2 M36 25 2 3 2 M45 40 3 4 3 M61 21 2 2 2 yazim 1. bas. 2. bas. 3. bas. 4. bas. A'dan farkli A 20 18 9 13 0 B 19 17 10 14 4 C 0 38 9 13 20 Ic ice kosul derinligi 3; sinirlar K2:K4 hucrelerinden okunuyor.
B yazımı A’dan tam 4 kayıtta ayrılıyor ve o dördü sınırdaki dört kayıttır; kalan 56
kayıt için < ile <= aynı şeyi söyler. Farkın küçük görünmesi bir güvence değildir: fark her
zaman sınırdaki kayıt sayısı kadardır ve o sayı veriye bağlıdır.
C yazımı başka bir hata sınıfını gösteriyor. Sınırlar, çarpanlar ve işaretler doğru; yalnız
25 sınırı 10 sınırından önce denendi. İlk tutan dal kazandığı için 10 m³’ün altındaki her kayıt
ilk katmanda “25’in altında” bulunup ikinci basamağa yazıldı. Birinci basamak tamamen
boşaldı: 20 kayıt yanlış basamağa düştü. Sayfada ne hata değeri var ne boş hücre, yalnız hiç
görünmeyen bir basamak numarası.
Basamaktan Tutara
Basamak tek başına rapor edilmez, tutara çevrilir. Aşağıdaki blok üç tutar yazımını karşılaştırır, sınır farkını fatura düzeyinde basar ve aynı toplamı üreten üç yazımı kararın nerede durduğuna göre tarar.
// tutar.mjs — basamak karari tutara cevrilir: duz ve kademeli hesap, iki sinir yazimi. import { sayfa, deger, kaydir, SATIR } from "./tarife.mjs"; const CARPAN = (o) => `eger(F2${o}$K$2,$L$2,eger(F2${o}$K$3,$L$3,eger(F2${o}$K$4,$L$4,$L$5)))`; const TUTAR = { "duz <=": "=$H$2*F2*" + CARPAN("<=") + "+$H$3", "duz <": "=$H$2*F2*" + CARPAN("<") + "+$H$3", kademeli: "=$H$2*(enk(F2,$K$2)*$L$2+enb(0,enk(F2,$K$3)-$K$2)*$L$3" + "+enb(0,enk(F2,$K$4)-$K$3)*$L$4+enb(0,F2-$K$4)*$L$5)+$H$3", }; const H = sayfa(); const sutun = (f) => { const K = { ...H }; for (let i = 0; i < SATIR; i++) K["N" + (i + 2)] = kaydir(f, 0, i); return Array.from({ length: SATIR }, (_, i) => deger(K, "N" + (i + 2))); }; const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); const D = Object.fromEntries(Object.entries(TUTAR).map(([a, f]) => [a, sutun(f)])); const t = (d) => d.reduce((a, b) => a + b, 0); // Esik 0,005 ucret birimidir: tutarlar kurus altinda ayirt edilmez. const ESIK = 0.005; const y = g([12, 12, 12, 12]); console.log(y(["yazim", "toplam", "duz <='den", "oynayan"])); for (const [a, d] of Object.entries(D)) console.log(y([a, t(d).toFixed(2), (t(d) - t(D["duz <="])).toFixed(2), d.filter((v, i) => Math.abs(v - D["duz <="][i]) >= ESIK).length])); const z = g([10, 12, 12, 12, 10]); console.log("\n" + z(["hucre", "faturalanan", "duz <=", "duz <", "fark %"])); let enBuyuk = 0; for (let i = 0; i < SATIR; i++) { const a = D["duz <="][i], b = D["duz <"][i]; if (Math.abs(a - b) < ESIK) continue; enBuyuk = Math.max(enBuyuk, 100 * Math.abs(b - a) / a); console.log(z(["N" + (i + 2), deger(H, "F" + (i + 2)), a.toFixed(2), b.toFixed(2), (100 * (b - a) / a).toFixed(1)])); } console.log(`\nSinir karari toplami yuzde ` + `${(100 * Math.abs(t(D["duz <"]) - t(D["duz <="])) / t(D["duz <="])).toFixed(2)} oynatti, ` + `tek bir faturayi en cok yuzde ${enBuyuk.toFixed(1)} oynatti.`); console.log(`Kademeli hesap sinir yazimindan etkilenmez: kosul yok, dilim var.`); // Geri okuma taramasi: ayni tutari uc yazim uretiyor, kararin yeri farkli. const CARP = (o, K, L) => `eger(F2${o}${K[0]},${L[0]},eger(F2${o}${K[1]},${L[1]},` + `eger(F2${o}${K[2]},${L[2]},${L[3]})))`; const HUC = ["$K$2", "$K$3", "$K$4"], CL = ["$L$2", "$L$3", "$L$4", "$L$5"]; const YAZIM = { tek: { N: "=$H$2*F2*" + CARP("<=", HUC, CL) + "+$H$3" }, "iki sutun": { M: "=" + CARP("<=", HUC, CL), N: "=$H$2*F2*M2+$H$3" }, gomulu: { N: "=$H$2*F2*" + CARP("<=", [10, 25, 40], [1, 1.4, 1.9, 2.6]) + "+$H$3" }, }; const kur = (S, y) => { const K = { ...S }; for (let i = 0; i < SATIR; i++) for (const [c, f] of Object.entries(y)) K[c + (i + 2)] = kaydir(f, 0, i); return K; }; const Z = { ...H, K3: 30 }; // ikinci sinir 25 -> 30 m3 const s = g([12, 12, 10, 8, 10]); console.log("\n" + s(["yazim", "toplam", "derinlik", "adim", "pesinden"])); for (const [ad, y] of Object.entries(YAZIM)) { const K = kur(H, y), W = kur(Z, y); const N = Array.from({ length: SATIR }, (_, i) => deger(K, "N" + (i + 2))); const N2 = Array.from({ length: SATIR }, (_, i) => deger(W, "N" + (i + 2))); // Basamagi geri okumak icin okunacak hucre: tutar formulunde kosul varsa karar hicbir // hucrede yazili degildir, uc karsilastirma yeniden degerlendirilir. const metin = Object.values(y).join(""); console.log(s([ad, N.reduce((a, b) => a + b, 0).toFixed(2), (metin.match(/eger\(/g) ?? []).length, /eger\(/.test(y.N) ? 0 : 1, N.filter((v, i) => Math.abs(v - N2[i]) >= ESIK).length])); } const iki = [10, 25, 40].filter((v) => Object.values(H).filter((x) => x === v).length > 1); console.log(`\nBasamak sinirlari sayfada iki yerde duruyor (H6:H8 ve K2:K4): ` + `${iki.join(", ")} m3. K3 degisince H7 degismez.`);
yazim toplam duz <='den oynayan duz <= 26219.52 0.00 0 duz < 26698.32 478.80 4 kademeli 19507.92 -6711.60 40 hucre faturalanan duz <= duz < fark % N2 10 109.00 142.60 30.8 N30 25 319.00 424.00 32.9 N36 25 319.00 424.00 32.9 N45 40 663.40 898.60 35.5 Sinir karari toplami yuzde 1.83 oynatti, tek bir faturayi en cok yuzde 35.5 oynatti. Kademeli hesap sinir yazimindan etkilenmez: kosul yok, dilim var. yazim toplam derinlik adim pesinden tek 26219.52 3 0 6 iki sutun 26219.52 3 1 6 gomulu 26219.52 3 0 0 Basamak sinirlari sayfada iki yerde duruyor (H6:H8 ve K2:K4): 10, 25, 40 m3. K3 degisince H7 degismez.
Birinci tablo dersin birinci sayısını veriyor: 26 219,52 ücret birimi. Sınır karşılaştırması değişince 26 698,32 oluyor, fark 478,80 — yüzde 1,83, bir kontrol toplamının gözünden kaçacak kadar küçük. İkinci tablo aynı farkı kayıt düzeyinde gösteriyor: dört abonenin faturası yüzde 30,8 ile 35,5 arasında değişti. Toplamda küçük olan bir karar, tek tek kayıtlarda küçük değildir.
Kademeli hesap üçüncü bir sayı veriyor: 19 507,92, düz hesaptan 6 711,60 daha az ve 60 kaydın
40’ında farklı. İkisi de savunulabilir: biri tüketimin tamamını ulaşılan basamağın çarpanıyla
ücretlendirir, öteki her dilimi kendi çarpanıyla. Kademeli yazımda hiç koşul yoktur; dilimler
enk ve enb ile kesilir, bu yüzden sınır işareti kararı o hesapta hiç sorulmaz. Bir kararın
maliyeti, yanındaki kararın ne olduğuna bağlıdır.
Son tablo dersin ikinci sayısıdır. Üç yazım da aynı toplamı üretiyor ve üçünde de koşul
derinliği 3. Ayrım son iki sütunda: iki sutun yazımında çarpan M hücresine yazılır ve bir
kaydın basamağını öğrenmek için 1 hücre okunur; ötekilerde basamak hiçbir hücrede durmaz —
0 adım, okunacak yer yok. Sınır 30 m³’e çıkarıldığında hücreye başvuran iki yazımda 6 tutar
peşinden geldi, gömülü yazımda 0; sonuncusu 26 219,52’yi göstermeye devam eder ve artık
yanlıştır.
Kapanış satırı sayfanın çelişkisini yazıyor: 10, 25 ve 40 hem parametre bloğunda hem tarife tablosunda duruyor. Formüller tarife tablosuna başvurur, ama sayfaya bakan biri parametre bloğunu güncelleyebilir ve hiçbir hesap kıpırdamaz. Aynı kararın iki kopyası, bir karar değildir.
Özet
- İç içe koşulda katmanlar soldan sağa denenir ve ilk tutan dal kazanır; sıra bir karardır. Sıra bozulunca 20 kayıt yanlış basamağa düştü ve birinci basamak tamamen boşaldı.
- Sınır karşılaştırması yalnız sınırda duran kayıtları etkiler:
<=yerine<yazmak 4 kaydı oynattı. O dördünü sınıra oturtan şey sınır değil, yuvarlama kararıdır. - Aynı karar toplamı yüzde 1,83 oynattı ama dört faturayı yüzde 30,8 ile 35,5 arasında oynattı. Toplama bakan bir kontrol bu farkı göremez.
- Aynı toplamı üreten üç yazımdan yalnız birinde basamak bir hücrede yazılıdır; ötekilerde karar 3 katmanlı koşulun içindedir ve sayfada okunacak yeri yoktur.
- Aynı sınır sayfada iki yerde durduğunda biri değişip öteki kalabilir; ikinci kopya kararı güçlendirmez, belirsizleştirir.
Sonraki Adım
Buraya kadar her karşılaştırma sayısaldı. Sayfanın öteki yarısı metindir: abone kodu, ad, bölge. Sonraki adımda saha ziyareti kayıtları abone kayıtlarıyla abone kodu üzerinden eşleştirilir. İki tablodaki kodlar gözle bakıldığında aynıdır, ama biri sonunda görünmeyen bir boşluk taşır, biri büyük harfle yazılmıştır. Sonraki ders bu kayıtların kaçının eşleşmediğini sayar, kırpma ve harf dönüşümü kararlarının kaç eşleşmeyi geri getirdiğini ölçer ve bu kararların sayfada nerede durduğunu gösterir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.