Slumgenerator i c++ för matteoperationer

Permalänk

Slumgenerator i c++ för matteoperationer

Jag och min kompis diskuterade vad medlet av fyra tärningar där man varje gång tar bort den minsta tärningen skulle vara, om man kastade en massa gånger.

tex 3,3,1,4 -> 3+3+4=10 -> ögonmedelvärde = 10

Vi hittade inget matematiskt sätt att lösa det på, så jag försökte skriva ett program i stället:

#include <iostream>
#include <stdlib.h>
#include <windows.h>
using namespace std;

int main()
{
double kvot = 0, s1 = 0, s2 = 0,b1 = 0,b = 0;
long int t1, t2, t3 ,t4, a;
cout << "Hur manga forsok?" << endl;
cin >> a;
b = 0;

while (b <= a) //själva slumpandet
{
srand(GetTickCount()); //rand seedaren
t1 = rand()%6 + 1; //tärning 1..
t2 = rand()%6 + 1;
t3 = rand()%6 + 1;
t4 = rand()%6 + 1;
s1 = t1+ t2+ t3+ t4 + s2 - min(min(t1,t2),min(t3,t4)); //tärning
//1+2+3+4 + föregående summan - den minsta tärningen
s2 = s1;
b1 = b + 1; //antal "kast" ökar med ett varje gång
b = b1;
}
kvot = s1/b1;
cout << t1 << " " << t2 <<" " << t3 << " " << t4 << endl;
cout << kvot << endl;
system("pause");
}

Men det går cirka 25000 tärningskast innan "rand()-seedern" hinner ändras. 25000 kast blir alltså lika.
Jag skulle vilja att varje kast blev "unikt" för att få ett vettigt medelvärde. Finns det någon snäll person som sitter inne på en lösning?

Permalänk
Medlem

Kör srand(GetTickCount()) en gång vid programstart, det räcker, kör du den fler gånger kommer den nollställas och börja om på samma värde hela tiden då GetTickCount() inte ändrar sig så ofta.

Sen kan man skriva
s1 += t1+ t2+ t3+ t4 - min(min(t1,t2),min(t3,t4));
istället för
s1 = t1+ t2+ t3+ t4 + s2 - min(min(t1,t2),min(t3,t4));
s2 = s1

och
b++;
istället för
b1 = b + 1;
b = b1;

Ta inte illa upp men det verkar som du tror att man inte kan tilldela en variabel sitt eget värde eller en formel som innehåller sitt eget värde. Det går att göra.

b = b + 1; // det kommer öka b med 1

Permalänk
Medlem

Finns det någon *nixsätt att slumpa ett nytt tal varje ms utan att skriva en egen ms-funktion?

Visa signatur

Into the Web Browser for iPhone, http://www.intothewebbrowser.com/

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av oggee
Finns det någon *nixsätt att slumpa ett nytt tal varje ms utan att skriva en egen ms-funktion?

Det är bara att använda rand(), den slumpar ut ett nytt värde varje gång, man behöver inte köra srand() efter varje slumpning.

Permalänk
Medlem

Här skulle jag vilja ha ett svar av raol-klass.

Visa signatur

Övriga Ämnen - Enbart för människor som är seriösa!

Permalänk

Tack så mycket, programmet verkar ge ett vettigt svar nu. Upplysningarna om algebrareglerna(?) i c++ är också uppskattad.

100000000 försök
ger medlet
12.2442
på 30 sekunder

Permalänk
Medlem

Nu vet jag inte om jag förstog dig, men jag gör ett försök:

a += 1; // a = a + 1; a -= 1; // a = a - 1; a *= 2; // a = a * 2; a /= 2; // a = a / 2; a %= 2; // a = a % 2; Modulus, resten i en delning. 7 % 2 == 1, 11 % 4 == 3 a++; // a = a + 1; Detta utförs efter användning ++a; // a = a + 1; Detta utförs innan användning a-- / --a // lika men med minus a ^= 2; // a = a XOR 2; Sök efter XOR, jag orkar inte förklara int a=0; if (a++ == 1) cout << "Detta utförs aldrig då a får värdet 1 efter jämförelsen"; a = 0; if (++a == 1) cout << "Detta skrivs ut då a ökas med ett innan den jämför"; a <<= 2; // a = a << 2; Flyttar bitarna i talet a två steg åt vänster. // Ser talet binärt ut 00101101 så blir det i detta fallet 10110100 a >>= 2; // a = a >> 2; Flyttar åt höger istället

Det var väl det viktigaste. Har säkert missat något. Kan vara värt att nämna att en integer delat med en integer alltid blir en integer, så 7/2 blir 3 och inte 3,5. Vill man ha 3,5 så får man skriva 7.0/2 (7/2.0, 7.0/2.0 eller med floats...) då den kommer returnera en float eller double istället.

Permalänk

Kan inte säga annat än tack igen.
C++ verkar vara ett bra språk att göra räkneoperationer i. IALF snabbt.
Gjorde faktisk samma program i TI-BASIC till T-83, men då TI-BASIC är ett väldigt långsamt språk...så hann batterierna dö innan jag fick ett svar.

Permalänk
Medlem

Du bör räkna ut innan hur långt du bör köra programmet.

För TI-BASIC i TI-83:an är det rimligt att vänta på 100-1000 loopar om det inte görs något besvärligt inuti den (som att beräkna integraler); i C++ på en vanlig dator (=min ) brukar 1-10 miljoner loopar vara rimligt att vänta på. Med rimligt menar jag några sekunder.

edit: Btw, ni är medvetna om att det går mycket snabbare att kolla alla kombinationer istället (och då få ett exakt svar)? Det är 6^4 = 1296 st.

Visa signatur

:€

Permalänk
Medlem

Efter 200000000 kast med 4 tärningar så anser jag att medlet blir 12.0333
Det tog sin lilla tid i matlab typ 3 minuter. heh

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av eighty
edit: Btw, ni är medvetna om att det går mycket snabbare att kolla alla kombinationer istället (och då få ett exakt svar)? Det är 6^4 = 1296 st.

Snabbare att räkna, ja. Mer kod, ja.

Permalänk
Medlem

Nä, det skulle bli färre rader. De fyra raderna där man tilldelar varje tärning ett nytt värde byter man ut mot fyra loopar. Man slipper dessutom inkludera cstdlib. Bättre, snabbare, kortare.

Visa signatur

:€

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Don_Tomaso
Det är bara att använda rand(), den slumpar ut ett nytt värde varje gång, man behöver inte köra srand() efter varje slumpning.

srand(time_h(NULL))(eller vafan det är ) ger bara en ny slump varje sekund?

Visa signatur

Into the Web Browser for iPhone, http://www.intothewebbrowser.com/

Permalänk

Tänkte bara bevaka tråden, men hittade inte hur man gör så jag fick lov att skriva för att göra det :/

Visa signatur

| i5 10600k@4,7 Ghz | AMD 6800 | 4Ghz RAM | 1 TB m.2 |

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av oggee
srand(time_h(NULL))(eller vafan det är ) ger bara en ny slump varje sekund?

En ny slumpseed ja. rand() returnerar nya slumpade värden utefter slumpseeden och den senaste slumpningen. Seedningen räcker med att köra en gång per programstart.

Kanske tom är så att rand() kör en srand(värdet den returnerar), skulle inte förvåna mig.

kaptenperre: Längst ner på sidan finns "Uppmärksamma mig vid ändring av tråden".

int s=0; for (int a=1; a<=6; a++) for (int b=1; b<=6; b++) for (int c=1; c<=6; c++) for (int d=1; d<=6; d++) s += a+b+c+d - min(min(a, b), min(c, d)); cout << ((float)s / 1296) << endl;

srand(GetTickCount()); int s=0, t=0, p=0, a[4]={0}; while (t++ < 1000000) { for (p=0; p<4; p++) a[p] = rand()%6+1; s += a[0] + a[1] + a[2] + a[3] - min(min(a[0], a[1]), min(a[2], a[3])); } cout << ((float)s / 1000000) << endl;

Lika många rader.

Okokok, du vinner eighty.
edit: Hehu, färre rader, definen räknas inte.

#define rnd (rand()%6+1) srand(GetTickCount()); int s=0, t=0, m=0, n=0; while (t++ < 1000000) s += (m = rnd) + ((n = rnd) < m ? m=n : n) + ((n = rnd) < m ? m=n : n) + ((n = rnd) < m ? m=n : n) - m; cout << ((float)s / 1000000) << endl;

Permalänk
Medlem

I matlab

sort(round(5*rand(4,1000)+1)); sum(sum(ans(2:4,:)))/1000;

lagom mycket kod

eller varför inte det exakta svaret

3*((21/6)*(6^4-5^4)+(20/5)*(5^4-4^4)+(18/4)*(4^4-3^4)+(15/3)*(3^4-2^4)+(11/2)*(2^4-1^4)+6)/6^4 = 11.6331

Hmm. gjorde jag någon tabbe där kanske...
så här tänkte jag
chansen att en etta bortfaller är
6^4-5^4
och medelsumma när den bortfaller är
21/6 * 3

edit igen: Nä fan jag är säker på att jag missar något, men kan inte se något direkt fel.
vill du ta dig en titt eighty? jag tror matematiken talar för sig själv

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Don_Tomaso
Okokok, du vinner eighty.
edit: Hehu, färre rader, definen räknas inte.

...fusk...;)

Räknar du s+=-grejen som en enda rad? Isf får du räkna alla fyra loopar i "mitt" exempel som en eftersom det bara tillhör en sats. Annars kontrar jag med att bara loopa igenom en variabel från 1 till 1296, och "utvinner" a,b,c,d från den med / och %. Orkar inte koda det, men utförandet är väl uppenbart.

Btw vinner du en rad om du struntar i srand(). Finns ingen mening med att använda en ny seed varje gång man kör programmet.

edit: Micket: ska kolla på det imorgon om ingen annan hinner före. Jag kollade lite på den förut och failade och gav upp för stunden.

Visa signatur

:€

Permalänk
Citat:

Ursprungligen inskrivet av eighty
Du bör räkna ut innan hur långt du bör köra programmet.
...
edit: Btw, ni är medvetna om att det går mycket snabbare att kolla alla kombinationer istället (och då få ett exakt svar)? Det är 6^4 = 1296 st.

Att räkna ut alla kombinatoner kräver också ett program. Dvs någon som räknar.
Finns det, teoretisk, någon formel som räknar ut medlet? Utan att behöva dra summan av alla kombinationer genom antalet kombinationer?

Den här typen av uppgifter överstiger vida min kunskap i sannolikhetslära

Permalänk

#include <cstdlib> #include <iostream> #include <windows.h> using namespace std; int main(int argc, char *argv[]) { srand(GetTickCount()); int sum = 0; for(int n = 0; n < 10000000; n++) { char dice[4]; dice[0] = rand()%6+1; dice[1] = rand()%6+1; dice[2] = rand()%6+1; dice[3] = rand()%6+1; char lowest = 6; for(int i = 0; i<4 ;i++) if(dice[i] < lowest) lowest = dice[i]; sum += dice[0] + dice[1] + dice[2] + dice[3] - lowest; } cout << sum / 10000000.0 << endl; system("PAUSE"); return EXIT_SUCCESS; }

Jag får 12,24.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av vetebulleN
Att räkna ut alla kombinatoner kräver också ett program. Dvs någon som räknar.
Finns det, teoretisk, någon formel som räknar ut medlet? Utan att behöva dra summan av alla kombinationer genom antalet kombinationer?

Den här typen av uppgifter överstiger vida min kunskap i sannolikhetslära

Vi tog det till mattetråden, jag hade missat en liten detalj i mitt tidigare lösningsförslag i tråden.
Raol fann dock vad jag och eighty missade

http://forum.sweclockers.com/showthread.php?s=&postid=4943508...

här kan du läsa om det, mitt, eightys och raols inlägg är de relevanta

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av vetebulleN
Att räkna ut alla kombinatoner kräver också ett program. Dvs någon som räknar.

Nej. Om du t ex har

for (kör 5 ggr) for (kör 6 ggr) for (kör 7 ggr) bajs

Så kommer bajs-raden att köras 5*6*7 gånger.

Visa signatur

:€

Permalänk
Medlem

Nog måste den bästa approachen vara att räkna ut enligt gängse formel än att testa sig fram med ett antal utfall. Det ni testar med det senare är snarare "korrektheten" i implementationen av slumptalsgeneratorn snarare än slumptalen som sådana, rätta mig om jag har fel.

Så jag får väl slå ett slag för mickets inlägg. Men matlab är annars ett bra verktyg för att leka med tal och matematik. Orkar man inte fixa det räcker Excel faktiskt ganska långt.

Permalänk
Medlem

Enklast är väl att ta alla möjliga kombinationer istället för att bara slumpa blint,
1,1,1,1;1,1,1,2...;6,6,6,6
Då får man väl ett exakt värde, eller hur?
6^4 = 1296 st
edit: Jag gissar att frågeställningen dök upp då ni skulle skapa en karaktär till drakar och demoner, korrekt?
med

<?php function sum_three_highest($dice) { sort($dice); return $dice[1]+$dice[2]+$dice[3]; } $sum = 0; for($dice[0]=1;$dice[0]<7;$dice[0]++) { for($dice[1]=1;$dice[1]<7;$dice[1]++) { for($dice[2]=1;$dice[2]<7;$dice[2]++) { for($dice[3]=1;$dice[3]<7;$dice[3]++) { $sum += sum_three_highest($dice); } } } } echo $sum/1296; ?>

kom jag fram till resultatet 12.2445987654 vilket borde vara en approximation av ett exakt värde.
får se om jag orkar fundera på en formel för ett exakt värde
---
att dela upp det i 6 fall (lägsta är 1,..,6) funkar väl inte? I så fall måste man även beräkna sannolikheten för att lägsta ska vara exempelvis 3.

Visa signatur

På internet kommunicerar vi mestadels med text. Så om du skriver, och stavar som en idiot, så kommer du troligtvis att bli betraktad som en sådan.
Förmågan att kunna ändra åsikt skiljer den vise från den envise.

Permalänk
Medlem

på en rad i haskell, alla kombinationer:

f = sum [fun (x:y:z:[w]) | x <- [1..6], y <- [1..6], z <- [1..6], w <- [1..6]] / 6^4 where fun = sum . tail . sort

Edit: Ngn kankse tycker det var en för lång rad, ändrat nu.

Permalänk
Medlem

Ah, haskell e fint

Jag har en annan fråga som har att göra med slumptal, men tar den i egen tråd kom jag just på...

Permalänk
Medlem

Varför ska du generera slum för? Finns det inte tillräckligt mycket slum ändå?

Visa signatur

Mina boktips: Clean codeHead First Design PatternsHead First Object-oriented Analysis and Design
Innovation distinguishes between a leader and a follower. — Steve Jobs

Permalänk
Citat:

Ursprungligen inskrivet av Micket
Vi tog det till mattetråden, jag hade missat en liten detalj i mitt tidigare lösningsförslag i tråden.
Raol fann dock vad jag och eighty missade

http://forum.sweclockers.com/showthread.php?s=&postid=4943508...

här kan du läsa om det, mitt, eightys och raols inlägg är de relevanta

Tackar, vad man egentligen kan läsa ut av problemet är att problem på den här nivån torde lösas lättast genom praktiska förksök. Mer tidsödande utan dator bara...
Dock är det ju alltid snyggare att lösa det mattematisk

Citat:

Ursprungligen inskrivet av Thurén
edit: Jag gissar att frågeställningen dök upp då ni skulle skapa en karaktär till drakar och demoner, korrekt?[/B]

Kunde inte bli mer korrekt. Tjusningen med DoD är ju att sitta och diskturera allt från huruvida skogstroll bara kan bo i skogen eller inte till vad en stop mjöd egentligen borde kosta...så i det allmäna boffrandet borde ju GE-medlet komma upp.

Permalänk
Medlem

3 tärningar utan omkast etc är det enda rätta

Visa signatur

På internet kommunicerar vi mestadels med text. Så om du skriver, och stavar som en idiot, så kommer du troligtvis att bli betraktad som en sådan.
Förmågan att kunna ändra åsikt skiljer den vise från den envise.

Permalänk

Kanske det, betydligt lättare att räkna ut medlet IALF

Permalänk
Medlem

Åh, saknar DoD sessionerna! Det var alldeles förlänge sen. Jag skrev "generera-charaktär-program" då med, i Pascal. Det var tider det.