6 Nisan 2023

Sayılar

JavaScript’te tüm sayılar 64-bit formatında tutulur IEEE-754, buna “double precision” da denir.

Sayılar ile ilgili bilinenlerin üzerinden tekrar geçecek olunursa.

Sayıyı yazmanın birçok yolu

Diyelim ki 1 milyar yazmak istiyorsunuz. Şu şekilde:

let milyar = 1000000000;

Fakat gerçek hayatta bu kadar 0 yan yana yazdığınızda karışma şansı olduğundan bunun yerine 1milyar veya 7.3milyar gibi yazılabilmektedir. Aynı özellik JavaScript için de geçerli. Fakat bu defa sayıdaki 0 sayısı "e" ile birlikte kullanılmalıdır:

let milyar = 1e9;  // 1 milyar 1 ve 9 sıfırdan oluşmaktadır.

alert( 7.3e9 );  // 7.3 milyar (7,300,000,000)
1e3 = 1 * 1000
1.23e6 = 1.23 * 1000000

Çok küçük bir sayıya bakıldığında. Örneğin 1 mikrosaniye ( saniyenin milyonda 1’i):

let ms = 0.000001;

Aynı şekilde "e" yardımcı olabilir. 0 ları yazmak yerine :

let ms = 1e-6; // 1'in soluna 6 tane 0

Şeklinde tanımlayabilirsiniz. 0.000001 gördüğünüz gibi 6 tane sıfır bulunmaktadır. Bundan dolayı 1e-6 şeklinde yazılabilir.

// -3 demek 1'in yanında 3 tane sıfır koy ve sayıyı böl.
1e-3 = 1 / 1000 (=0.001)

// -6 demek 1'in yanına 6 tane sıfır koy ve sayıyı böl.
1.23e-6 = 1.23 / 1000000 (=0.00000123)

HexaDecimal, binary ve octal sayılar.

Hexadecimal sayılar JavaScript’te çoğunlukla renklerde, karakter çevrimlerinde ve birçok alanda kullanılmaktadır. Bundan dolayı 0x gibi kolay yazım biçimine sahiptir. Diğer türlü sayı kullanılması gerekmektedir.

Örneğin:

alert( 0xff ); // 255
alert( 0xFF ); // 255 (büyük küçük harf farkı yoktur)

Binary ve Octal sayı sistemleri ise çok nadir kullanılmaktadır fakat 0b veya 0o önekleri mevcuttur.

let a = 0b11111111; // binary 255
let b = 0o377; // octal 255

alert( a == b ); // true, iki sayı da aynıdır.

3 çeşit sayısal sistem desteklenmiştir. Diğer sayısal sistemler için ise parseInt kullanılmalıdır.

toString(taban)

num.toString(base) verilen tabana göre karakter dizisini döndürür.

Örneğin:

let sayi = 255;

alert( sayi.toString(16) );  // ff
alert( sayi.toString(2) );   // 11111111

taban 2 ile 36 arasında değişebilir. Varsayılanı 10dur.

Genel olarak kullanımı şu şekildedir:

  • 16-tabanı hex renkler için, karakter çevrimleri için kullanılır. 0..9 ve A..F arası kullanılabilir.

  • 2-tabanı bit tipindeki uygulamalar için kullanılır. Sadece 0 veya 1’dir değerlerini alabilir.

  • 36-tabanı maximum bir basamak 0..9 veya A..Z arası kullanılabilir. Bu da demek oluyor ki bütün latin alfabesi sayıları tanımlamak için kullnılabilir. Bu uzun sayısal bir değeri daha kısa bir değee çevirmek istendiğinde kullanılabilir. Örneğin URL kısaltma kolay bir şekilde 36-taban’nda ifade edilebilir.

    alert( 123456..toString(36) ); // 2n9c
İki nokta ile metod çağırımı

.. şeklinde yazım, hatalı bir yazım değildir. Eğer sayı üzerinden doğrudan metod çağırılmak isteniyor ise .. yazımı kullanılıri

Eğer tek nokta olursa:123456.toString(36) hata meydana gelir. Çünkü tek nokta olduğunda JavaScript ondalık sayı olarak algılar ve hata verir. Fakat bir tane daha nokta koyulursa JavaScript ondalık sayı olmadığını anladar ve doğrudan metoda gider.

Şu şekilde de yazılabilir: (123456).toString(36).

Yuvarlama

Sayılar ile yapılan önemli işlemlerden biri de yuvarlama işlemidir.

Yuvarlama işlemi için birçok dahili fonksiyon bulunmaktadır:

Math.floor
Aşağı yuvarlar: 3.1 3 , -1.1 -2 olur.
Math.ceil
Yukarı yuvarlar: 3.1 4, -1.1 -1 olur.
Math.round
En yakın tam sayıya yuvarlar: 3.1 3, 3.6 4 ve -1.1 -1 olur.
Math.trunc (Internet Explorer desteklemez)
Ondalık bölümü siler: 3.1 3, -1.1 -1 olur.

Tablo şeklinde aşağıdaki gibi özetlenebilir:

Math.floor Math.ceil Math.round Math.trunc
3.1 3 4 3 3
3.6 3 4 4 3
-1.1 -2 -1 -1 -1
-1.6 -2 -1 -2 -1

Bu fonksiyonlar ondalık sayılar için önünüze gelebilecek tüm farklılıkları kapsar. Fakat ya ondalık bölümden n. basamağını yuvarlamak isterseniz?

Örneğin 1.2345 diye bir sayı olsun ve bunu 2 basamağa yuvarlamak istiyorsunuz 1.23 gibi

Bunu yapmak için iki yol bulunmaktadır:

  1. Çarp ve Böl.

    Örneğin 2. basamaktan sonrasını yuvarlamak istiyorsanız bunu 100 ile çarpıp sonra tekrar 100 e bölerseniz istediğinizi elde etmiş olursunuz.

    let num = 1.23456;
    
    alert( Math.floor(num * 100) / 100 ); // 1.23456 -> 123.456 -> 123 -> 1.23
  2. toFixed(n) kullanarak ondalık bölümde n basamaktan sonrası için yuvarlama yapılabilir.

    let num = 12.34;
    alert( num.toFixed(1) ); // "12.3"

    Bu Math.round gibi tam sayıya yakınlığına göre yukarıya veya aşağıya yuvarlar:

    let num = 12.36;
    alert( num.toFixed(1) ); // "12.4"

    toFixed karakter dizisi döndürür. Eğer ondalık bölüm argümandan kısa ise sona 0 eklenir.

    let num = 12.34;
    alert( num.toFixed(5) ); // "12.34000", ondalık bölüm 5 basamaklı yapılmıştır.

    Önüne artı koyarak veya Number() fonksiyonunu kullaranak bunu sayıya çevirebilirsiniz: +num.toFixed(5).

Küsürlü hesaplama

JavaScript sayıları IEEE-754 ifade edilir, bunlardan 52’si basamakları tutar. 11 tanesi ise ondalık bölümleri tutar ( tam sayılar için bu 11 bit sıfır olur) ve 1 bit işareti tutar.

Eğer sayı çok büyükse 64 bit alanın dışına çıkabilir bu da sonsuz döndürür.

alert( 1e500 ); // Sonsuz

Çok ta açık olmamakla birlikte çoğunlukla ola gelen bir problem ise küsür kaybıdır.

Aşağıdaki olayı test edin:

alert( 0.1 + 0.2 == 0.3 ); // false

Doğru eğer 0.1 ile 0.2’nin toplamının 0.3 olduğunu sanıyorsanız yanılıyorsunuz.

Peki 0.3 değilse ne o zaman ?

alert( 0.1 + 0.2 ); // 0.30000000000000004

Yok artık! Burada yanlış karşılaştırmanın sonuçlarını gördünüz. Düşünün bir e-ticaret sitesi yapıyorsunuz. Kullanıcı 0.10₺ ve 0.20₺ lik iki tane çiklet ekledi sepetine. Sonuçta toplam $0.30000000000000004 oldu. Sitenize gelen kişinin kafası karışacaktır.

Peki neden böyle bir şey oluyor?

Sayı hafızada binary formatta tutulur. Fakat ondalık bölümleri 0.1, 0.2 gibi desimal sistemde çok basit gibi duran sayılar aslında bitmez bir binary forma sahiptir.

0.1 nedir? 1 in 10 bölümünden elde edilir. Onluk sistemde kolayca gösterilir. Fakat ondalık sistemde 1/3 sonsuza kadar 0.3333(3) şeklinde devam eder.

Öyleyse 10’a bölüm onluk sayılarda sorun yaratmazken 3’e bölüm sorun yaratmaktadır. Aynı neden dolayı, bu defa binary sistem , aynı şekilde sonsuza kadar gider, 2’nin katları ile bölüm tam sonuç verecektir. Fakat 1/10 sonsuza kadar giden bir binary değer verir.

Aslında 0.1 veya 0.2 tam olarak saklanamaz, tıpkı 1/3’ün tam olarak saklanamaması gibi.

IEEE-754 bunu en yakın değere yuvarlayarak çözmektedir. Bu kurallar bizim “küçük küsürleri” görmemizi engeller.

Örneğin:

alert( 0.1.toFixed(20) ); // 0.10000000000000000555

Toplandığında ise “küsür kayıpları” üst üste eklenir. Bundan dolayı 0.1 + 0.2 0.3 etmez.

Sadece JavaScript bu sorundan muzdarip değildir

Bu problemler diğer programlama dillerinde de mevcuttur.

PHP, Java, C, Perl, Ruby gibi diller de aslında aynı değeri verir. Çalıştıkları sistem aynı şekilde binary(ikili) sistemdir.

Bu problemden nasıl kurtulunur? Tabi bunun için bir kaç yöntem mevcuttur:

  1. toFixed(n) metodu yardımı ile yuvarlayabilirsiniz:

    let toplam = 0.1 + 0.2;
    alert( toplam.toFixed(2) ); // 0.30

    Unutmayın toFixed her zaman karakter dizisi döndürür. .'dan sonra 2 basamak alır. Eğer e-ticaret sistemi üzerinde çalışıyorsanız bu gerçekten kullanışlıdır çünkü sonuç 0.30 olmalıdır. Diğer hallerde önüne + koyarak bunu sayıya çevirebilirsiniz:

    let toplam = 0.1 + 0.2;
    alert( +toplam.toFixed(2) ); // 0.3
  2. Geçici olarak sayılar tam sayıya çevrilio sonradan geri döndürülebilir. Aşağıdaki gibi çalışır:

    alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3

    Aşağıdaki gibi çalışır 0.1 * 10 = 1 ve 0.2 * 10 = 2 sonrasında iki tam sayı hiçbir ondalık bölüm olmadan toplanır böylece küsürat kaybı ortadan kalkar.

  3. Eğer e-ticaret sitesi üzerinde çalışıyorsanız. En radikal çözüm tüm küsüratları kuruş olarak kaydedip hiç küsürat kullanmamak olabilir. Fakat ya %30 indirip yapmak isterseniz? Pratikte bu kullanım çok nadirdir. Bundan dolayı yukarıdaki iki şekilde problem çözülebilir.

Tuhaf tarafı

Aşağıdaki kodu çalıştırın:

// Merhaba ben kendi kendine artan sayıyım.!
alert( 9999999999999999 ); // shows 10000000000000000

Bu da küsürat kaybından meydana gelir. Bir sayıda 64 bit bulunmaktadır. 52 tanesi basamak tutmaktadır. Fakat bu durumda bu basamak yeterli değildir. Bundan dolayı en etkisiz basamak kaybolur.

JavaScript böyle bir durumda hata vermez. Belirli formata göre en iyi şekilde sayıyı yerleştirmeye çalışır. Fakat bu format yeterli büyüklükte değil.

Sıfırlar

Diğer bir komik olay ise 0 ve -0’ın varlığıdır.

İşaret bir bit ile tutulduğundan dolayı tüm sayıların - ve + lı değerleri bulunmaktadır.

Çoğu durumda bu ayrım soruna anlaşılamaz. Çünkü operatörler ikisine de aynı şekilde davranır.

Testler: isFinite ve isNaN

Hatırlarsanız iki tane özel sayı vardı.

  • Infinite (ve -Infinite), bu sayı hersayıdan büyüktür, veya her sayıdan küçüktür.
  • NaN ise bir hata göstergesidir.

Her ikisi de number tipine aittirler, fakat “normal” sayı değildirler. Bundan dolayı bunların kontrolü için özel fonksiyonlar bulunmaktadır.

  • isNaN(deger) argümanı sayıya çevirir ve sayı olup olmadığını kontrol eder.

    alert( isNaN(NaN) ); // true
    alert( isNaN("str") ); // true

    Bu fonksiyona ihtiyacınız var mı? Sadece === NaN kullanılsa ? Malesef ihtiyaç var. NaN kendi başına hiçbir şeye eşit değildir, hatta kendisine bile:

    alert( NaN === NaN ); // false
  • isFinite(deger) argümanı sayıya çevirir ve normal sayı ise true değil ise NaN/Infinity/-Infinity döndürür:

    alert( isFinite("15") ); // true
    alert( isFinite("str") ); // false,  NaN döndürür.
    alert( isFinite(Infinity) ); // false, Infinity döndürür.

Bazen isFinite karakterin sayı olup olmadığını kontrol için kullanılır:

let num = +prompt("Bir sayı giriniz", '');

// Infinity girmediğiniz taktirde `true` olacaktır. -Infinity diye bir sayı yoktur.
alert( isFinite(num) );

Aklınızda bulunsun tüm boş veya sadece boşluk tuşu ile yazılan tüm değerler 0 olarak kabul edilir isFinite’de bu şekilde çalışır.

Object.is ile karşılaştırma

Özel bir dahili metod olan Object.is ile değerler === gibi karşılaştırılabilir. İki durum için daha güvenlidir denebilir:

  1. NaN ile çalışır: Object.is(NaN, NaN) === true bu iyi
  2. 0 ve -0 farklıdır: Object.is(0, -0) === false,neredeyse hiç kullanılmaz, ama yinede teknik olarak farklıdırlar.

Tüm durumlarda Object.is(a, b) a === b ile aynıdır.

Bu tür karşılaştırma genelde JavaScript içerisinde kullanılır. JavaScript içinde eğer algoritma iki değerin kesinlikle aynı olup olmadığını kontrol etmek istiyorsa Object.is kullanılır SameValue

parseInt ve parseFloat

+ veya Number() kullanılarak sayıya çevirme sıkı bir çevirmedir. Eğer argüman sayı değilse hata verir:

alert( +"100px" ); // NaN

Eğer başta veya sonda boşluk varsa bunlar görmezden gelinir.

Fakat gerçek hayatta değerler, "100px" veya "12pt" gibi birim ekleri alabilir. Birçok ülkenin para birimi sona veya başa gelir. Bundan dolayı 15₺ gibi değerler kullanıldığında önemli olan sayı bölümü olabilir.

parseInt ve parseFloat tam olarak bunlar için kullanılır.

Karakter dizisinden sayıları “okuyabildikleri kadar” okurlar. Hata olduğu durumda sayıyı dönderir. parseInt tam sayı dönderirken parseFloat küsüratlı sayı dönderir.

alert( parseInt('100px') ); // 100
alert( parseFloat('12.5em') ); // 12.5

alert( parseInt('12.3') ); // 12, sadece tamsayı bölümü alındı
alert( parseFloat('12.3.4') ); // 12.3, birinci noktadan sonra yeniden nokta gördüğünde işlemi tamamladı

Eğer hiçbir basamak okunamazsa NaN dönderirler.

alert( parseInt('a123') ); // NaN, ilk harf işlemi durdurur.
parseInt in ikinci argümanı : parseInt(str,radix)

parseInt fonksiyonu isteğe bağlı olarak ikinci bir parametreye sahiptir. Bu sayı tabanını belirtir, böylece parseInt karakter olarak yazılmış hex sayılarını veya binary değerlerini de ayrıştırabilir.

alert( parseInt('0xff', 16) ); // 255
alert( parseInt('ff', 16) ); // 255, 0x olmadan da çalışır

alert( parseInt('2n9c', 36) ); // 123456

Diğer matematik fonksiyonları

JavaScript dahilinde matematiksel fonksiyonların ve sabitlerin bulunduğu küçük bir kütüphane mevcuttur. Math

Birkaç örnek:

Math.random()

0 ile 1 (1 dahil değil) arasında rasgele sayı üretir.

alert( Math.random() ); // 0.1234567894322
alert( Math.random() ); // 0.5435252343232
alert( Math.random() ); // ... (herhangi bir rasgele sayı)
Math.max(a, b, c...) / Math.min(a, b, c...)

Verilen değerlerden en büyüğünü veya en küçüğünü döndüren fonksiyon

alert( Math.max(3, 5, -10, 0, 1) ); // 5
alert( Math.min(1, 2) ); // 1
Math.pow(n, üs)

n’in üssünü döndürür.

alert( Math.pow(2, 10) ); // 2'nin 10 üssü = 1024

math objesi daha birçok fonksiyon ve sabit barındırmaktadır. Trigonometri de bunlara dahildir. Math objesi dökümantasyonu

Özet

Büyük sayıları yazmak için:

  • "e" nin yanına kaç tane sıfır varsa onu yazın. Örneğin : 123e6 = 123 ün yanına 6 tane 0 yaz demektir.
  • "e" den sonra yazılan negatif sayı ise kaç tane sıfır varsa önüne bir koy ve değeri bu sayıya böl demektir.

Farklı sayı sistemleri:

  • Sayıları doğrudan hex olarak (0x), octal olarak(0o) veya binary(ikili) (0b) olarak yazmak mümkündür.
  • parseInt(str,taban) verilen tabana göre karakteri ayrıştırmaya yarar. Taban2ile36` aralığında olmalıdır ( 2 ve 36 dahil)
  • num.toString(taban) ise bir sayıyı karakter dizisine verilen tabanda yazmaya yarar.

12pt ve 100px gibi değerleri sayıya çevirme:

  • parseInt/parseFloat hafif çevirimler için kullanılabilir, karakter görene kadar sayıları tutar ve karakter görürse tuttuklarını geri dönderir.

Ondalık bölüm:

  • Math.floor, Math.ceil, Math.trunc, Math.round veya num.toFixed(basamak) kullanarak yuvarlayabilirsiniz.
  • Küsüratlarda olan sorunları sayılarla çalışırken her zaman aklınızda tutmalısınız.

Daha fazla matematik fonksiyonu:

  • Gerektiği zaman Math adresinden incelenebilir. Kütüphane çok küçük olsa da basit gereksinimleri karşılar.

Görevler

önem: 5

Kullanıcıya iki defa değer soran ve bu değerleri toplayan kodu yazınız.

Demoyu çalıştır

P.S. Tiplerle ilgili bir numara var.

let a = +prompt("İlk numara", "");
let b = +prompt("İkinci numara?", "");

alert( a + b );

prompt öncesi koyulan + işareti alınan değeri doğrudan sayıya çevirir.

Diğer türlü girilen değerler string olarak algılanır toplama yerine birleştirilir: "1" + "2" = "12"

önem: 4

Dökümantasyona göre Math.round ve toFixed en yakın sayıya yuvarlarlar: 0..4 arası aşağı yuvarlarken 5..9 arası yukarı yuvarlar.

Örneğin:

alert( 1.35.toFixed(1) ); // 1.4

Peki aşağıdaki örnekte neden 6.4 e yuvarlamadı da 6.3 e yuvarladı?

alert( 6.35.toFixed(1) ); // 6.3

6.35 in doğru bir şekilde yuvarlanması için ne yapılmalıdır?

Aslında 6.35’in decimal bölümü sonsuz binarydir. Böyle bir durumda kesinlik kaybına uğrarlar.

alert( 6.35.toFixed(20) ); // 6.34999999999999964473

Bu kesinlik kaybı sayının küçülmesine veya büyümesine neden olabilir. Bu örnekte sayı çok çok küçük bir oranda küçülüyor bundan dolayı aşağıya yuvarladı.

1.35 için ise:

alert( 1.35.toFixed(20) ); // 1.35000000000000008882

Sayı çok küçük bir değer ile büyük limitin üstüne çıktı, bundan dolayı yukarıya yuvarladı.

Peki 6.35 için bu problem nasıl çözülebilir

Tam sayı değerini yuvarlama değerine yaklaştırılırsa problem çözülür:

alert( (6.35 * 10).toFixed(20) ); // 63.50000000000000000000

63.5 hiçbir kayba uğramıyor dikkat ederseniz. Çünkü 0.5 lik fark aslında 1/2. 2 ve üstü ile yapılan işlemler binary sistemde tam olarak ifade edildiğinden dolayı bu problem çözülmektedir.

alert( Math.round(6.35 * 10) / 10); // 6.35 -> 63.5 -> 64(yuvarlandı) -> 6.4
önem: 5

sayiOku adında bir fonksiyon oluşturun. Bu fonksiyon kullanıcı sayı girene kadar prompt ile değer alsın.

Sonuç sayı döndürmelidir.

Ziyaretci boş değer girerek veya “İPTAL” tuşuna basarak programı durdurabilir. Bu durumda fonksiyon null döndürmelidir.

Demoyu çalıştır

Testler ile korunaklı olan aç.

function sayiOku() {
  let sayi;

  do {
    sayi = prompt("Lütfen bir sayı giriniz?", 0);
  } while ( !isFinite(sayi) );

  if (sayi === null || sayi === '') return null;

  return +sayi;
}

alert(`Oku: ${sayiOku()}`);

Kod null/boş değer kontrolünden dolayı biraz garip görünebilir.

“sayı” gelene kadar değerler kontrol edilmelidir. null ve boş satır true döndürür. Çünkü numerik olarak bu değerler 0’dır.

Çözümü testler korunaklı alanda olacak şekilde aç.

önem: 4

Aşağıdaki döngü neden sonsuzdur ve hiçbir zaman bitmez? s

let i = 0;
while (i != 10) {
  i += 0.2;
}

Çünkü i hiçbir zaman 10 olmaz.

Aşağıdaki kodu çalıştırın ve gerçek i değerini görün:

let i = 0;
while (i < 11) {
  i += 0.2;
  if (i > 9.8 && i < 10.2) alert( i );
}

hiçbirisi tam olarak 10 olmayacaktır.

Bunun olmasının nedeni 0.2 eklediğimizde kesinlik kaybı olur.

Sonuç: Eğer ondalıklı sayılar ise çalışıyorsanız eşitlik kontrolünü iyice kontrol edin.

önem: 2

JavaScript dahilinde Math.random() 0 ile 1 arasında ( 1 dahil değil) rasgele bir sayı döndürür.

Öyle bir fonksiyon yazın ki random(min,max) bu değerler arasında rasgele ondalıklı sayı üreten bir fonksiyon yazın.

Örnekler:

alert( random(1, 5) ); // 1.2345623452
alert( random(1, 5) ); // 3.7894332423
alert( random(1, 5) ); // 4.3435234525

Normalde 0…1 arasında olan değerleri min ve max arasına "haritalamamız` gerekmektedir.

Çözüm iki bölümden oluşur:

  1. Eğer 0…1 arasında seçilen rasgele sayı max-min ile çarpılırsa, değer 0..1 arasından 0..max-min arasına kadar büyütülür.
  2. Eğer min eklenirse, bu aralık min den max a kadar olur.

Fonksiyon:

function random(min, max) {
  return min + Math.random() * (max - min);
}

alert( random(1, 5) );
alert( random(1, 5) );
alert( random(1, 5) );
önem: 2

randomInteger(min,max) adında bir fonksiyon yazın. Bu fonksiyon sadece min ve max değerleri arasında tam sayı döndürsün.(min ve max ikisi de dahil)

Her defasında min..max aynı olasılıkla seçilmelidir.

Örnek:

alert( random(1, 5) ); // 1
alert( random(1, 5) ); // 3
alert( random(1, 5) ); // 5

Bir önceki görevi temel alabilirsiniz.

Basit fakat yanlış çözüm

Basit yöntem, min ile max arasında rasgele bir değer bulup bunu yuvarlamaktır.

function randomInteger(min, max) {
  let rand = min + Math.random() * (max - min);
  return Math.round(rand);
}

alert( randomInteger(1, 3) );

Fonksiyon çalışır fakat yanlıştır. min ve max ın kenar değerlerinin seçilmesi diğer değerlere göre iki kat azdır.

Eğer yukarıdaki örneği birçok defa çalıştırırsanız en fazla 2 nin döndüğünü göreceksiniz.

Bu böyle olur çünkü Math.round() , 1..3 arasında rasgele değerler alır ve aşağıdaki gibi bunları yuvarlar:

1    ... ile 1.4999999999  arası  1
1.5  ... ile 2.4999999999  arası 2
2.5  ... ile 2.9999999999  arası 3

Gördüğünüz gibi 1’in 2ye göre seçilme olasılı 2 defa daha azdır. 3 için de aynıdır.

Doğru çözüm

Aslında birçok doğru çözüm vardır. Bir tanesi, aralık sınırlarının ayarlanmasıdır. Her defasında aynı aralık seçildiğinden emin olunmalıdır. 0.5 ile 2.5 arasında değerler üretilebilir. Bu şekilde kenarlara olasılık için ağırlık eklenmiş olur.

function randomInteger(min, max) {
  // (min-0.5) ile (max+0.5) arasında
  let rand = min - 0.5 + Math.random() * (max - min + 1);
  return Math.round(rand);
}

alert( randomInteger(1, 3) );

Diğer bir alternatif ise Math.floor kullanılarak min ile max+1 aralığından rasgele bir sayı seçilmesidr.

function randomInteger(min, max) {
  // rasgele min ile (max+1) arasındadır.
  let rand = min + Math.random() * (max + 1 - min);
  return Math.floor(rand);
}

alert( randomInteger(1, 3) );

Şimdi ise aralıklar şu şekilde haritalanır:

1  ... ile 1.9999999999  arası 1 olur
2  ... ile 2.9999999999  arası 2 olur
3  ... ile 3.9999999999  arası 3 olur

Tüm aralıklar aynı boyutlara sahiptir. Son tahlilde hepsi aynı olasılığa sahiptir.

Eğitim haritası