Birlamchi taqsimlanmagan tasodifiy tamsayı yaratish

Men bir qator oralig'ida raqam yaratish uchun ko'proq imkoniyatga ega raqamni ishlab chiqarish yo'lini topishga urindim. Berilgan:

rnum = r.nextInt(5) + 1;//+ 1 to exclude 0

1 dan 5 gacha (0 va 4 bo'lsa, + 1 olib tashlangan bo'lsa) butunlay tasodifiy sonni ishlab chiqaradi. Men nima qilishni xohlasam, 1-dan 5-gachani kamroq ishlab chiqaraman va 3-raqamni yarataman. Bunga harakat qildim:

int[] classes = {1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5};
System.out.println("Class " +  classes[r.nextInt(15)]);//logs the output

Biroq, buning sababi quyidagicha: (10 marta takroriy nashr)

Class 2
Class 3
Class 1
Class 4
Class 3
Class 4
Class 2
Class 3
Class 2
Class 5

Biroq, buning samarasi yaxshi emas. Bundan tashqari, raqamni olishda ishlatiladigan tasodifiy sonlar generatori markaziy qiymatga e'tibor berish o'rniga butunlay tasodifiy bo'lib, natijada yuqoridagi chiqimni amalga oshiradi. 3 faqat 30% ni tashkil etadi, bu juda past. 2, shuningdek, vaqtning 30% ni tashkil etadi, ya'ni (bu testda) 3 deb hisoblash imkoniyati mavjud.

Shunday qilib, qator oralig'ida raqam yaratish uchun yuqori ehtimollik bilan tasodifiy sonni qanday qilib yaratishim mumkin?

1
Kerakli taqsimot oraliq oralig'iga to'g'ri keladi, bu holatda 3. Men qiladigan usul umumiy yechim sifatida ishlamaydi va agar masofa 1-1000 bo'lsa, u ko'p sonli qo'lda raqam kiritishni talab qiladi.
qo'shib qo'ydi muallif Zoe, manba
Vaqtning taxminan 50-60% ni qo'lga kiritish va qolgan qiymatlar (masalan, 2 va 4 foizga har birining 15-20% ni va har biri 1 va 5% dan 10% gacha)
qo'shib qo'ydi muallif Zoe, manba
Vaqtning taxminan 50-60% ni qo'lga kiritish va qolgan qiymatlar (masalan, 2 va 4 foizga har birining 15-20% ni va har biri 1 va 5% dan 10% gacha)
qo'shib qo'ydi muallif Zoe, manba
avysk: har doim ham barchani olish imkoniyati, lekin ishlab chiqarish usuli o'rtacha qiymatlarni yaratishga qaratilgan bo'lsa, uni ishlab chiqarish imkoniyati past bo'ladi. Barchasini olish imkoniyati bor, lekin u faqat bir raqamni ishlab chiqarganidan ancha past. O'rtacha: 3 O'rtacha: 2 O'rtacha: 2 O'rtacha: 3 O'rtacha: 2 O'rtacha: 2 O'rtacha: 2 O'rtacha: 3 O'rtacha: 2 O'rtacha: 3
qo'shib qo'ydi muallif Zoe, manba
avysk: har doim ham barchani olish imkoniyati, lekin ishlab chiqarish usuli o'rtacha qiymatlarni yaratishga qaratilgan bo'lsa, uni ishlab chiqarish imkoniyati past bo'ladi. Barchasini olish imkoniyati bor, lekin u faqat bir raqamni ishlab chiqarganidan ancha past. O'rtacha: 3 O'rtacha: 2 O'rtacha: 2 O'rtacha: 3 O'rtacha: 2 O'rtacha: 2 O'rtacha: 2 O'rtacha: 3 O'rtacha: 2 O'rtacha: 3
qo'shib qo'ydi muallif Zoe, manba
10 marta aniq ehtimollikni aniqlash va kerakli taqsimotni olish uchun juda kichik namunadir. Sizning yo'lingiz yaxshi.
qo'shib qo'ydi muallif JB Nizet, manba
10 marta aniq ehtimollikni aniqlash va kerakli taqsimotni olish uchun juda kichik namunadir. Sizning yo'lingiz yaxshi.
qo'shib qo'ydi muallif JB Nizet, manba
Ko'proq qayta ko'rib chiqishga namunasi bilan: ideone.com/uFhzKA
qo'shib qo'ydi muallif JB Nizet, manba
Ko'proq qayta ko'rib chiqishga namunasi bilan: ideone.com/uFhzKA
qo'shib qo'ydi muallif JB Nizet, manba
Endi sizni olib qoldingiz. rost. Sizningcha, taklif qilingan yechimning foizlari qanday?
qo'shib qo'ydi muallif hasan83, manba
Mening taklif qilingan yechim oldindan belgilangan qatorni o'z ichiga olmaydi.
qo'shib qo'ydi muallif hasan83, manba
Mening taklif qilingan yechim oldindan belgilangan qatorni o'z ichiga olmaydi.
qo'shib qo'ydi muallif hasan83, manba
@avysk siz xohlagan tarqatishni xohlaysizmi? O'ylaymanki, bu savolga aniq javob beradigan narsa yo'q.
qo'shib qo'ydi muallif hasan83, manba
"@JBNizet" ga qo'shiladi. bosimni for loopga qo'shing va undan yaxshi saytga ega bo'lish uchun foizni hisoblash uchun chiqishni dasturiy jihatdan hisoblang. 1000 döngünün yinelemesini taklif qilaman.
qo'shib qo'ydi muallif hasan83, manba
"@JBNizet" ga qo'shiladi. bosimni for loopga qo'shing va undan yaxshi saytga ega bo'lish uchun foizni hisoblash uchun chiqishni dasturiy jihatdan hisoblang. 1000 döngünün yinelemesini taklif qilaman.
qo'shib qo'ydi muallif hasan83, manba
(5) tasodifiy 1dan 5gacha va tasodifiy 1 dan 5 gacha +1 bo'lsa, nima qilishimiz mumkin. Ya'ni, bizning maqsadimizga 100% erishiladi.
qo'shib qo'ydi muallif hasan83, manba
(5) tasodifiy 1dan 5gacha va tasodifiy 1 dan 5 gacha +1 bo'lsa, nima qilishimiz mumkin. Ya'ni, bizning maqsadimizga 100% erishiladi.
qo'shib qo'ydi muallif hasan83, manba
Jadvallarni ishlab chiqarishni avtomatlashtirishingiz mumkin, siz 1000 ta qiymatni qo'l bilan kiritishingiz kerak emas.
qo'shib qo'ydi muallif Marvin, manba
Jadvallarni ishlab chiqarishni avtomatlashtirishingiz mumkin, siz 1000 ta qiymatni qo'l bilan kiritishingiz kerak emas.
qo'shib qo'ydi muallif Marvin, manba
Siz olishni istagan har bir raqam uchun ehtimollikni belgilashingiz mumkin bo'lgan javobni qo'shing.
qo'shib qo'ydi muallif avysk, manba
Siz olishni istagan har bir raqam uchun ehtimollikni belgilashingiz mumkin bo'lgan javobni qo'shing.
qo'shib qo'ydi muallif avysk, manba
@ hasan83 istalgan tarqatish "siz olishni istagan 3 soniya" degan ma'noni anglatadi. Vaqtning 90% ni olish vazifasi vaqtning uchdan uch qismini olish uchun vazifadan farq qiladi. (Va u faqat 3s uchun amal qiladi).
qo'shib qo'ydi muallif avysk, manba
Bu erda sizda ba'zi bir noto'g'ri tushunish bor. Imkoniyatning bir maxsus namunadagi chastotasi bilan hech qanday aloqasi yo'q. Siz tanlagan namunadagi qancha yozuvlardan qat'iy nazar (bu juda kam bo'lsa-da), masalan, namunaning faqat 1s dan iborat bo'lish ehtimoli mavjud.
qo'shib qo'ydi muallif avysk, manba
@ hasan83 istalgan tarqatish "siz olishni istagan 3 soniya" degan ma'noni anglatadi. Vaqtning 90% ni olish vazifasi vaqtning uchdan uch qismini olish uchun vazifadan farq qiladi. (Va u faqat 3s uchun amal qiladi).
qo'shib qo'ydi muallif avysk, manba
@LunarWatcher Rahmat, men bilaman: D Faqat asl savolda ("3s dan 2-lardan bir xil miqdorda ishlab chiqqani kabi ishlamaydi)" degan gap to'g'ri emasligini aytmoqdaman.
qo'shib qo'ydi muallif avysk, manba
@ hasan83 shubhasiz, bu o'rta qiymatlar tomon yo'naltiriladi, lekin biz bu erda istalgan tarqatishni bilmaymiz ...
qo'shib qo'ydi muallif avysk, manba
@ hasan83 shubhasiz, bu o'rta qiymatlar tomon yo'naltiriladi, lekin biz bu erda istalgan tarqatishni bilmaymiz ...
qo'shib qo'ydi muallif avysk, manba
Ba'zi real hayot illyustratsiyasi: bosh olish ehtimolligi 1/2 bo'lsa-da va quyruq olish ehtimoli 1/2 bo'lsa ham, siz 10 ta tanga tashlashingiz va faqat boshlarini olishingiz mumkin.
qo'shib qo'ydi muallif avysk, manba
Ba'zi real hayot illyustratsiyasi: bosh olish ehtimolligi 1/2 bo'lsa-da va quyruq olish ehtimoli 1/2 bo'lsa ham, siz 10 ta tanga tashlashingiz va faqat boshlarini olishingiz mumkin.
qo'shib qo'ydi muallif avysk, manba
Bu erda sizda ba'zi bir noto'g'ri tushunish bor. Imkoniyatning bir maxsus namunadagi chastotasi bilan hech qanday aloqasi yo'q. Siz tanlagan namunadagi qancha yozuvlardan qat'iy nazar (bu juda kam bo'lsa-da), masalan, namunaning faqat 1s dan iborat bo'lish ehtimoli mavjud.
qo'shib qo'ydi muallif avysk, manba
Tasodifiy o'zgarmaydigan uchun binomial taqsimot ni ko'rib chiqishingiz mumkin.
qo'shib qo'ydi muallif Monkey Supersonic, manba
Tasodifiy o'zgarmaydigan uchun binomial taqsimot ni ko'rib chiqishingiz mumkin.
qo'shib qo'ydi muallif Monkey Supersonic, manba

11 javoblar

Oddiy yondoshish, kerakli ehtimolliklar bo'lgan qator bilan boshlash edi.

import java.util.Random;

class Main {

    public static int getOneNumber(double[] probs, Random rnd) {
        double r = rnd.nextDouble();
        for (int j = 0; j < probs.length; j++) {
            if (r < probs[j]) {
                return j;
            }
            r -= probs[j];
        }
        throw new RuntimeException("probabilities should sum to 1");
    }


    public static void main(String[] args) {

       //Desired probabilities
        double[] probabilities = {
            0.05,//0
            0.15,//1
            0.6,//2
            0.15,//3
            0.05 };//4

        Random rnd = new Random();
        for (int i = 0; i < 20; i++) {
            System.out.println(getOneNumber(probabilities, rnd));
        }
    }
}

Bu erda quyidagi g'oyalar keltirilgan. Biz 0 dan 1 gacha tasodifiy sonni ishlab chiqaramiz. Endi biz tekshiramiz: 0,05dan pastroqmi? Agar shunday bo'lsa, biz 0 ga qaytamiz va bu ehtimollik 0.05 bilan amalga oshiriladi. Agar shunday bo'lmasa, bizning raqamimiz 0,05 va 0,15 oralig'ida ekanligini tekshiramiz (undan 0,05ni chiqarib, 0,1 bilan taqqoslash yo'li bilan). Agar u (bu ehtimollik 0,15-0,05 = 0,1 bilan sodir bo'lsa) - biz oldik. Agar u bo'lmasa, biz tasodifiy sonning 0.15 va 0.75 orasida ekanligini tekshiramiz.

3
qo'shib qo'ydi

Oddiy yondoshish, kerakli ehtimolliklar bo'lgan qator bilan boshlash edi.

import java.util.Random;

class Main {

    public static int getOneNumber(double[] probs, Random rnd) {
        double r = rnd.nextDouble();
        for (int j = 0; j < probs.length; j++) {
            if (r < probs[j]) {
                return j;
            }
            r -= probs[j];
        }
        throw new RuntimeException("probabilities should sum to 1");
    }


    public static void main(String[] args) {

       //Desired probabilities
        double[] probabilities = {
            0.05,//0
            0.15,//1
            0.6,//2
            0.15,//3
            0.05 };//4

        Random rnd = new Random();
        for (int i = 0; i < 20; i++) {
            System.out.println(getOneNumber(probabilities, rnd));
        }
    }
}

Bu erda quyidagi g'oyalar keltirilgan. Biz 0 dan 1 gacha tasodifiy sonni ishlab chiqaramiz. Endi biz tekshiramiz: 0,05dan pastroqmi? Agar shunday bo'lsa, biz 0 ga qaytamiz va bu ehtimollik 0.05 bilan amalga oshiriladi. Agar shunday bo'lmasa, bizning raqamimiz 0,05 va 0,15 oralig'ida ekanligini tekshiramiz (undan 0,05ni chiqarib, 0,1 bilan taqqoslash yo'li bilan). Agar u (bu ehtimollik 0,15-0,05 = 0,1 bilan sodir bo'lsa) - biz oldik. Agar u bo'lmasa, biz tasodifiy sonning 0.15 va 0.75 orasida ekanligini tekshiramiz.

3
qo'shib qo'ydi

Oddiy yondoshish, kerakli ehtimolliklar bo'lgan qator bilan boshlash edi.

import java.util.Random;

class Main {

    public static int getOneNumber(double[] probs, Random rnd) {
        double r = rnd.nextDouble();
        for (int j = 0; j < probs.length; j++) {
            if (r < probs[j]) {
                return j;
            }
            r -= probs[j];
        }
        throw new RuntimeException("probabilities should sum to 1");
    }


    public static void main(String[] args) {

       //Desired probabilities
        double[] probabilities = {
            0.05,//0
            0.15,//1
            0.6,//2
            0.15,//3
            0.05 };//4

        Random rnd = new Random();
        for (int i = 0; i < 20; i++) {
            System.out.println(getOneNumber(probabilities, rnd));
        }
    }
}

Bu erda quyidagi g'oyalar keltirilgan. Biz 0 dan 1 gacha tasodifiy sonni ishlab chiqaramiz. Endi biz tekshiramiz: 0,05dan pastroqmi? Agar shunday bo'lsa, biz 0 ga qaytamiz va bu ehtimollik 0.05 bilan amalga oshiriladi. Agar shunday bo'lmasa, bizning raqamimiz 0,05 va 0,15 oralig'ida ekanligini tekshiramiz (undan 0,05ni chiqarib, 0,1 bilan taqqoslash yo'li bilan). Agar u (bu ehtimollik 0,15-0,05 = 0,1 bilan sodir bo'lsa) - biz oldik. Agar u bo'lmasa, biz tasodifiy sonning 0.15 va 0.75 orasida ekanligini tekshiramiz.

3
qo'shib qo'ydi

Eng qulay usul:

0 va 1 o'rtasida suzuvchi nuqta raqami yarating. Qiymatni ikki marta olib tashlang va 1 Ushbu raqamni har qanday kuchga, misol uchun. 10. Uni 2-ga ajratib oling va 0,5 qo'shing

Natijangizni 15 bilan ko'paytiring

float fVal = Math.power(r.next()*2-1, 10)/2 + 0.5;
int iVal = Math.floor(fVal * 15);

int[] classes = {1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5};
System.out.println("Class " +  classes[iVal]);//logs the output

This should make your probability look more like a gaussian bell curve Maybe you want to read about Normal Distribution

1
qo'shib qo'ydi
r.next() bu erda ko'rsatilganidek, kirishni talab qiladi. Math.power, Math.pow o'rniga, ikki marta kiritishni talab qiladigan taniqli usuldir
qo'shib qo'ydi muallif Zoe, manba
Juda shov-shuvli Java-tasodifiy nextGaussian() ga ega, bu "o'rtacha qiymati 0,0 va standart og'ish 1,0"
qo'shib qo'ydi muallif tntxtnt, manba
Mumkin bo'lsa ham, u bu ishni bajarishga harakat qilayotgan narsalarni tushunishga olib kelmaydi.
qo'shib qo'ydi muallif Psi, manba

Eng qulay usul:

0 va 1 o'rtasida suzuvchi nuqta raqami yarating. Qiymatni ikki marta olib tashlang va 1 Ushbu raqamni har qanday kuchga, misol uchun. 10. Uni 2-ga ajratib oling va 0,5 qo'shing

Natijangizni 15 bilan ko'paytiring

float fVal = Math.power(r.next()*2-1, 10)/2 + 0.5;
int iVal = Math.floor(fVal * 15);

int[] classes = {1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5};
System.out.println("Class " +  classes[iVal]);//logs the output

This should make your probability look more like a gaussian bell curve Maybe you want to read about Normal Distribution

1
qo'shib qo'ydi
r.next() bu erda ko'rsatilganidek, kirishni talab qiladi. Math.power, Math.pow o'rniga, ikki marta kiritishni talab qiladigan taniqli usuldir
qo'shib qo'ydi muallif Zoe, manba
Juda shov-shuvli Java-tasodifiy nextGaussian() ga ega, bu "o'rtacha qiymati 0,0 va standart og'ish 1,0"
qo'shib qo'ydi muallif tntxtnt, manba
Mumkin bo'lsa ham, u bu ishni bajarishga harakat qilayotgan narsalarni tushunishga olib kelmaydi.
qo'shib qo'ydi muallif Psi, manba

Eng qulay usul:

0 va 1 o'rtasida suzuvchi nuqta raqami yarating. Qiymatni ikki marta olib tashlang va 1 Ushbu raqamni har qanday kuchga, misol uchun. 10. Uni 2-ga ajratib oling va 0,5 qo'shing

Natijangizni 15 bilan ko'paytiring

float fVal = Math.power(r.next()*2-1, 10)/2 + 0.5;
int iVal = Math.floor(fVal * 15);

int[] classes = {1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5};
System.out.println("Class " +  classes[iVal]);//logs the output

This should make your probability look more like a gaussian bell curve Maybe you want to read about Normal Distribution

1
qo'shib qo'ydi
r.next() bu erda ko'rsatilganidek, kirishni talab qiladi. Math.power, Math.pow o'rniga, ikki marta kiritishni talab qiladigan taniqli usuldir
qo'shib qo'ydi muallif Zoe, manba
Juda shov-shuvli Java-tasodifiy nextGaussian() ga ega, bu "o'rtacha qiymati 0,0 va standart og'ish 1,0"
qo'shib qo'ydi muallif tntxtnt, manba
Mumkin bo'lsa ham, u bu ishni bajarishga harakat qilayotgan narsalarni tushunishga olib kelmaydi.
qo'shib qo'ydi muallif Psi, manba

Start with a random number in [0, 1] and then raise it to the power of some positive number. Powers < 1 will bias upward, i.e. the numbers will be more likely to be higher than lower within [0, 1], and powers > 1 will bias downward. Then use multiplication and addition to shift the range of numbers from [0, 1] to your desired range.

double rnum,bias_factor;
int low,high;
//low, high and bias_factor are the inputs, then :
high = (low + high)/2;
for(int i = 0;i<=10;i++)
    {
        rnum = Math.random();
        rnum = Math.pow(rnum,bias_factor);
        rnum = (low + (high - low)*rnum)+1;
        System.out.println((int)rnum);
    }

Sharh:

high=(low + high)/2; 

makes the middle value of given range as the upper value of the range. Hence with a low bias factor the output gets biased towards the upper values of a range. For eg: Initially giving the inputs as high = 5, low = 1; and bias_factor = 0.4 generates more middle values(3's) in the range [1,5]. I think this might help: https://gamedev.stackexchange.com/questions/54551/using-random-numbers-with-a-bias

0
qo'shib qo'ydi

Start with a random number in [0, 1] and then raise it to the power of some positive number. Powers < 1 will bias upward, i.e. the numbers will be more likely to be higher than lower within [0, 1], and powers > 1 will bias downward. Then use multiplication and addition to shift the range of numbers from [0, 1] to your desired range.

double rnum,bias_factor;
int low,high;
//low, high and bias_factor are the inputs, then :
high = (low + high)/2;
for(int i = 0;i<=10;i++)
    {
        rnum = Math.random();
        rnum = Math.pow(rnum,bias_factor);
        rnum = (low + (high - low)*rnum)+1;
        System.out.println((int)rnum);
    }

Sharh:

high=(low + high)/2; 

makes the middle value of given range as the upper value of the range. Hence with a low bias factor the output gets biased towards the upper values of a range. For eg: Initially giving the inputs as high = 5, low = 1; and bias_factor = 0.4 generates more middle values(3's) in the range [1,5]. I think this might help: https://gamedev.stackexchange.com/questions/54551/using-random-numbers-with-a-bias

0
qo'shib qo'ydi

bu javobidagi algoritm bilan binomial taqsimotni ishlatib, tasodifiy qiymatlarni yaratishingiz mumkin:

public static int getBinomial(int n, double p) {
  int x = 0;
  for(int i = 0; i < n; i++) {
    if(Math.random() < p)
      x++;
  }
  return x;
}

O'rtacha qiymat 3 ga erishish uchun bunday funksiyani chaqiring:

getBinomial(4,0.5) +1;

Qiymatlar quyidagicha taqsimlanadi:

 1     2    3    4    5
1/16  1/4  3/8  1/4  1/16
0
qo'shib qo'ydi

bu javobidagi algoritm bilan binomial taqsimotni ishlatib, tasodifiy qiymatlarni yaratishingiz mumkin:

public static int getBinomial(int n, double p) {
  int x = 0;
  for(int i = 0; i < n; i++) {
    if(Math.random() < p)
      x++;
  }
  return x;
}

O'rtacha qiymat 3 ga erishish uchun bunday funksiyani chaqiring:

getBinomial(4,0.5) +1;

Qiymatlar quyidagicha taqsimlanadi:

 1     2    3    4    5
1/16  1/4  3/8  1/4  1/16
0
qo'shib qo'ydi

bu javobidagi algoritm bilan binomial taqsimotni ishlatib, tasodifiy qiymatlarni yaratishingiz mumkin:

public static int getBinomial(int n, double p) {
  int x = 0;
  for(int i = 0; i < n; i++) {
    if(Math.random() < p)
      x++;
  }
  return x;
}

O'rtacha qiymat 3 ga erishish uchun bunday funksiyani chaqiring:

getBinomial(4,0.5) +1;

Qiymatlar quyidagicha taqsimlanadi:

 1     2    3    4    5
1/16  1/4  3/8  1/4  1/16
0
qo'shib qo'ydi