{
  "ad": "yuzde-hesap",
  "surum": "1.1.0",
  "aciklama": "Bir değerin yüzdesini, iki değerin yüzde oranını, yüzde değişimini, yüzde ekleme veya çıkarmayı ve tersine yüzde hesabını yapan deterministik araç sözleşmesi.",
  "motor": {
    "nesne": "YuzdeMotor",
    "metot": "hesapla",
    "imza": "YuzdeMotor.hesapla(mod, girdi)",
    "basariZarfi": {
      "basarili": true,
      "cikti": "moda göre çıktı nesnesi",
      "uyarilar": []
    },
    "hataZarfi": {
      "basarili": false,
      "hata": {
        "kod": "hata kodu",
        "mesaj": "Türkçe hata mesajı",
        "alan": "varsa hatalı girdi alanı"
      },
      "uyarilar": []
    }
  },
  "sayiGirisi": {
    "tipler": [
      "number",
      "string"
    ],
    "kabulEdilenOrnekler": [
      "1.234,56",
      "1234,56",
      "1234.56",
      "1 234,56",
      "%18",
      "18%"
    ],
    "reddedilenOrnekler": [
      "1,2,3",
      "12.34.56",
      "1,2.3",
      "1.23,4"
    ],
    "gruplamaKurali": "Binlik ayraç kullanılan yazımda ilk gruptan sonraki her grup tam üç hanelidir. Nokta ve virgül birlikteyse yalnız son ayraç ondalıktır; önceki ayraç geçerli binlik grupları oluşturmalıdır.",
    "not": "Sonlu sayılar kabul edilir; yüzde işareti yalnız başta veya sonda olabilir. Bozuk ayraç düzenleri GECERSIZ_SAYI ile reddedilir."
  },
  "modlar": [
    {
      "id": "yuzdesi",
      "ad": "X'in %Y'si kaçtır?",
      "girdiler": [
        {
          "ad": "x",
          "tip": "number",
          "birim": "birimsiz",
          "zorunlu": true
        },
        {
          "ad": "y",
          "tip": "number",
          "birim": "yuzde",
          "zorunlu": true
        }
      ],
      "cikti": {
        "sonuc": {
          "tip": "number",
          "birim": "birimsiz"
        }
      },
      "formul": "sonuc = x * y / 100",
      "ornek": {
        "girdi": {
          "x": 250,
          "y": 18
        },
        "cikti": {
          "sonuc": 45
        }
      }
    },
    {
      "id": "yuzde-kaci",
      "ad": "X, Y'nin yüzde kaçıdır?",
      "girdiler": [
        {
          "ad": "x",
          "tip": "number",
          "birim": "birimsiz",
          "zorunlu": true
        },
        {
          "ad": "y",
          "tip": "number",
          "birim": "birimsiz",
          "rol": "butun",
          "zorunlu": true
        }
      ],
      "cikti": {
        "oran": {
          "tip": "number",
          "birim": "yuzde"
        }
      },
      "formul": "oran = (x / y) * 100",
      "ornek": {
        "girdi": {
          "x": 45,
          "y": 250
        },
        "cikti": {
          "oran": 18
        }
      }
    },
    {
      "id": "degisim",
      "ad": "Yüzde artış / azalış",
      "girdiler": [
        {
          "ad": "eski",
          "tip": "number",
          "birim": "birimsiz",
          "zorunlu": true
        },
        {
          "ad": "yeni",
          "tip": "number",
          "birim": "birimsiz",
          "zorunlu": true
        },
        {
          "ad": "yuzdeDegerleri",
          "tip": "boolean",
          "birim": "birimsiz",
          "zorunlu": false,
          "varsayilan": false,
          "aciklama": "true olduğunda eski ve yeni değer yüzde kabul edilir ve çıktıya yüzdePuani eklenir."
        }
      ],
      "cikti": {
        "degisim": {
          "tip": "number",
          "birim": "yuzde"
        },
        "fark": {
          "tip": "number",
          "birim": "birimsiz"
        },
        "yon": {
          "tip": "string",
          "degerler": [
            "artis",
            "azalis",
            "degismedi"
          ]
        },
        "yuzdePuani": {
          "tip": "number",
          "birim": "yuzde_puani",
          "kosullu": "Yalnız yuzdeDegerleri === true olduğunda döner."
        }
      },
      "formul": "degisim = ((yeni - eski) / eski) * 100; fark = yeni - eski; yon = degisim pozitifse artis, negatifse azalis, sıfırsa degismedi; yuzdeDegerleri true ise yuzdePuani = yeni - eski",
      "ornek": {
        "girdi": {
          "eski": 80,
          "yeni": 100
        },
        "cikti": {
          "degisim": 25,
          "fark": 20,
          "yon": "artis"
        }
      }
    },
    {
      "id": "ekle-cikar",
      "ad": "X'e %Y ekle / X'ten %Y çıkar",
      "girdiler": [
        {
          "ad": "x",
          "tip": "number",
          "birim": "birimsiz",
          "zorunlu": true
        },
        {
          "ad": "y",
          "tip": "number",
          "birim": "yuzde",
          "zorunlu": true
        },
        {
          "ad": "yon",
          "tip": "string",
          "birim": "secim",
          "degerler": [
            "ekle",
            "cikar"
          ],
          "zorunlu": true
        }
      ],
      "cikti": {
        "sonuc": {
          "tip": "number",
          "birim": "birimsiz"
        },
        "degisimTutari": {
          "tip": "number",
          "birim": "birimsiz"
        }
      },
      "formul": "yon ekle ise sonuc = x * (100 + y) / 100; yon cikar ise sonuc = x * (100 - y) / 100; degisimTutari = x * y / 100",
      "ornek": {
        "girdi": {
          "x": 1500,
          "y": 20,
          "yon": "ekle"
        },
        "cikti": {
          "sonuc": 1800,
          "degisimTutari": 300
        }
      }
    },
    {
      "id": "ters-yuzde",
      "ad": "Tersine yüzde",
      "girdiler": [
        {
          "ad": "z",
          "tip": "number",
          "birim": "birimsiz",
          "zorunlu": true
        },
        {
          "ad": "y",
          "tip": "number",
          "birim": "yuzde",
          "zorunlu": true
        },
        {
          "ad": "yon",
          "tip": "string",
          "birim": "secim",
          "degerler": [
            "artti",
            "azaldi"
          ],
          "zorunlu": true
        }
      ],
      "cikti": {
        "ilkDeger": {
          "tip": "number",
          "birim": "birimsiz"
        }
      },
      "formul": "yon artti ise ilkDeger = z * 100 / (100 + y); yon azaldi ise ilkDeger = z * 100 / (100 - y)",
      "ornek": {
        "girdi": {
          "z": 120,
          "y": 20,
          "yon": "artti"
        },
        "cikti": {
          "ilkDeger": 100
        }
      }
    }
  ],
  "ekOrnekler": {
    "sinirHata": {
      "aciklama": "Bütün sıfır olduğunda parça-bütün yüzde oranı tanımsızdır.",
      "mod": "yuzde-kaci",
      "girdi": {
        "x": 45,
        "y": 0
      },
      "beklenen": {
        "basarili": false,
        "hata": {
          "kod": "BOLEN_SIFIR",
          "mesaj": "Bütün sıfır olamaz.",
          "alan": "y"
        },
        "uyarilar": []
      }
    },
    "yuksekHassasiyet": {
      "aciklama": "Güvenli tam sayı sınırındaki değer yüzde 100 özdeşliğinde basamak kaybetmez.",
      "mod": "yuzdesi",
      "girdi": {
        "x": 9007199254740991,
        "y": 100
      },
      "beklenen": {
        "basarili": true,
        "cikti": {
          "sonuc": 9007199254740991
        },
        "uyarilar": []
      }
    },
    "yuksekBuyuklukCikarma": {
      "aciklama": "Yüksek büyüklükte yüzde 0,1 çıkarma, katsayıyı önceden yuvarlamadan kararlı 100-y payıyla değerlendirilir.",
      "mod": "ekle-cikar",
      "girdi": {
        "x": 100000000000000,
        "y": 0.1,
        "yon": "cikar"
      },
      "beklenen": {
        "basarili": true,
        "cikti": {
          "sonuc": 99900000000000,
          "degisimTutari": 100000000000
        },
        "uyarilar": []
      }
    },
    "yuksekBuyuklukTers": {
      "aciklama": "Yüksek büyüklükte yüzde 0,1 azalışın tersi, yuvarlanmış katsayıya bölünmeden kararlı 100-y payıyla değerlendirilir.",
      "mod": "ters-yuzde",
      "girdi": {
        "z": 99900000000000,
        "y": 0.1,
        "yon": "azaldi"
      },
      "beklenen": {
        "basarili": true,
        "cikti": {
          "ilkDeger": 100000000000000
        },
        "uyarilar": []
      }
    },
    "negatifSonDegerTersAzalis": {
      "aciklama": "Azalış yüzde 100’ü aştığında katsayı (100-y)/100 negatif olduğundan, negatif son değerin ilk değeri pozitif çıkar; YUZDEN_FAZLA_AZALIS uyarısı döner. İşaretten bağımsız olarak z ≠ 0 ise ilk değer son değerin ters işaretlisidir.",
      "mod": "ters-yuzde",
      "girdi": {
        "z": -100,
        "y": 120,
        "yon": "azaldi"
      },
      "beklenen": {
        "basarili": true,
        "cikti": {
          "ilkDeger": 500
        },
        "uyarilar": [
          {
            "kod": "YUZDEN_FAZLA_AZALIS",
            "mesaj": "%100’ü aşan azalışta katsayı negatiftir; sıfırdan farklı son değerin ilk değeri ters işaretli çıkar."
          }
        ]
      }
    }
  },
  "hatalar": [
    {
      "kod": "GECERSIZ_SAYI",
      "kosul": "Zorunlu sayısal girdi yoksa, sonlu değilse veya desteklenen TR/EN sayı yazımına ayrıştırılamıyorsa.",
      "mesaj": "İlgili alan için geçerli bir sayı girin.",
      "sonucUretilir": false
    },
    {
      "kod": "BOLEN_SIFIR",
      "kosul": "yuzde-kaci modunda y = 0 ise.",
      "mesaj": "Bütün sıfır olamaz.",
      "alan": "y",
      "sonucUretilir": false
    },
    {
      "kod": "ESKI_DEGER_SIFIR",
      "kosul": "degisim modunda eski = 0 ise.",
      "mesaj": "Eski değer sıfırken göreli yüzde değişim tanımlı değildir.",
      "alan": "eski",
      "sonucUretilir": false
    },
    {
      "kod": "GECERSIZ_YON",
      "kosul": "ekle-cikar modunda yon ekle/cikar veya ters-yuzde modunda artti/azaldi değilse.",
      "mesaj": "İşlem veya değişim yönü izin verilen değerlerden biri olmalıdır.",
      "alan": "yon",
      "sonucUretilir": false
    },
    {
      "kod": "TERS_YUZDE_BOLEN_SIFIR",
      "kosul": "ters-yuzde modunda hesaplanan bölen 0 ise; azaldi ve y = 100 veya artti ve y = -100.",
      "mesaj": "İlk değer hesaplanamaz; bölen sıfır olur.",
      "alan": "y",
      "sonucUretilir": false
    },
    {
      "kod": "SAYISAL_TASMA",
      "kosul": "Hesaplanan çıktı JavaScript sonlu sayı aralığını aşarsa.",
      "mesaj": "Sonuç desteklenen sayı aralığını aşıyor.",
      "sonucUretilir": false
    },
    {
      "kod": "GECERSIZ_MOD",
      "kosul": "mod tanımlı beş mod kimliğinden biri değilse.",
      "mesaj": "Bilinmeyen hesaplama modu.",
      "sonucUretilir": false
    }
  ],
  "uyarilar": [
    {
      "kod": "NEGATIF_TABAN",
      "kosul": "degisim modunda eski < 0 ise.",
      "mesaj": "Negatif tabanda yüzde değişim yanıltıcıdır."
    },
    {
      "kod": "YUZDEN_FAZLA_AZALIS",
      "kosul": "ters-yuzde modunda yon = azaldi ve y > 100 ise.",
      "mesaj": "%100’ü aşan azalışta katsayı negatiftir; sıfırdan farklı son değerin ilk değeri ters işaretli çıkar."
    }
  ],
  "sayisalDavranis": {
    "makineTipi": "JavaScript number (IEEE 754 binary64)",
    "araHesaplardaYuvarlama": false,
    "ciktiNormalizasyonu": "Yok; sonlu binary64 sonuç korunur, yalnız -0 değeri 0 olarak kanonikleştirilir.",
    "ciktiGosterimIcinYuvarlanir": false,
    "islemSirasi": "a*b/c biçimindeki yüzde ve oran işlemleri, sonlu gerçek sonucu ara taşma veya erken alt-taşmayla bozmamak için ikili büyüklüklere göre değerlendirilir. ekle-cikar doğrudan carpBol(x, 100 ± y, 100), ters-yuzde doğrudan carpBol(z, 100, 100 ± y) eşdeğerini kullanır.",
    "katsayiPolitikasi": "ekle-cikar ve ters-yuzde, (100 ± y)/100 katsayısını önceden binary64 sayıya yuvarlamaz; kararlı 100 ± y payını tek carpBol değerlendirmesinde korur. Ters işlemde sıfır bölen denetimi de 100 ± y payı üzerinden yapılır.",
    "arayuzVarsayilanOndalik": 2,
    "arayuzOndalikAraligi": [
      0,
      6
    ],
    "arayuzCiktiFormati": "TR",
    "arayuzPolitikasi": "0-6 ondalık seçimi yalnız sunum katmanına aittir; cikti alanlarını değiştirmez.",
    "gosterimYuvarlamaKurali": {
      "yontem": "sabit-basamak yuvarlama",
      "taban": 10,
      "hassasiyetAraligi": [0, 6],
      "varsayilanHassasiyet": 2,
      "yarimDurumYonu": "sifirdan-uzaga",
      "aciklama": "Sunum katmanı (formatTR) değeri seçili N ondalık basamağa yuvarlar. Tam olarak yarımda (sonraki basamak 5, gerisi sıfır) değer mutlak büyüklükçe yukarı yuvarlanır: 2,5 → 3 ve −2,5 → −3. Düşük büyüklükte ölçeklenmiş değer binary64 güvenli tam sayı sınırı içindeyse tek adımda; sınırı aştığında tam ve kesir kısımları ayrı dize tabanlı yuvarlanır ve en kısa String(number) kesri dilimlenmez. Bu yalnız sunum içindir; cikti sayılarını değiştirmez."
    }
  },
  "deterministik": true,
  "offline": true,
  "kaynak": "matematiksel tanım"
}
