Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [php]losowanie liczb zmienno przecinkowych
--ukaszq--
post
Post #1





Goście







Chce zrobic taki programik, ktory mi bedzie generował 10 liczb (losowo) z okreslonego przedzialu max i min. Tak aby suma tych liczb wylosowanych podzielona przez 10 dala wynik np 20,3.
Zrobilem tak:


  1. <?php
  2. $i=1;
  3. $srednia="20.3";
  4. $petla = "600";
  5. $max = "21.2";
  6. $min = "20.0";
  7.  
  8. while($i<=10){
  9. $los=rand($min,$max);
  10. echo "$los<br>";
  11. $suma += $los;
  12.  
  13. $i++;
  14. }
  15. $sum=$suma / $petla;
  16. echo round($sum,2);
  17. ?>


Tylko funkcja rand nie widzi mi liczb z dwoma miejscami po przecinku.
No i nie wiem jak to ustalic zeby te liczby daly mi konkretną srednią.
Prosze o pomoc...
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 7)
marcio
post
Post #2





Grupa: Zarejestrowani
Postów: 2 291
Pomógł: 156
Dołączył: 23.09.2007
Skąd: ITALY-MILAN

Ostrzeżenie: (10%)
X----


mOZE ZAmiast wyswietlac za pomoca echo sprobuj uzyc sprintf lub printf z operatorem %.2f??
Go to the top of the page
+Quote Post
nowotny
post
Post #3





Grupa: Zarejestrowani
Postów: 875
Pomógł: 122
Dołączył: 2.02.2008

Ostrzeżenie: (0%)
-----


rand" title="Zobacz w manualu PHP" target="_manual przyjmuje tylko wartości całkowite... Pomnóż sobie $min i $max przez 10, zapakuj do rand a to co ci rand zwróci podziel przez 10...
Go to the top of the page
+Quote Post
-Gość-
post
Post #4





Goście







No wpisalem tak pomnozylem przez 10 a pozniej podzielilem. Dzieki
Ale jak zrobic to aby te liczby wygenerowal tak aby wyszedl okreslony przeze mnie wynik z tych liczb?(IMG:http://forum.php.pl/style_emoticons/default/questionmark.gif)
Go to the top of the page
+Quote Post
ukaszq
post
Post #5





Grupa: Zarejestrowani
Postów: 128
Pomógł: 0
Dołączył: 8.08.2007

Ostrzeżenie: (10%)
X----


Czy zna ktos taką opcje jak to zrobic? By z okreslonej tak podzielil wynik by wyszla okreslona przeze mnie średnia?
Prosze o pomoc...
Go to the top of the page
+Quote Post
Hazel
post
Post #6





Grupa: Zarejestrowani
Postów: 492
Pomógł: 33
Dołączył: 16.08.2007
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Hehe, z tego co zrozumiałem to strasznie śmieszny problem (IMG:http://forum.php.pl/style_emoticons/default/biggrin.gif)
Chcesz po prostu nakazać randomowi żeby wylosował takie liczby, żeby ich średnia była z góry ustalona (IMG:http://forum.php.pl/style_emoticons/default/biggrin.gif)
No, powodzenia (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Nie da się tego w ten sposób zrobić. Random losuje takie liczby, jakie jemu sie podoba i nie możesz mu kazać nic konkretnego losować. Możesz natomiast wylosować jedną liczbę i tak dobrać drugą, żeby ich średnia była taka, jaką byś chciał (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg) To jedyny słuszny sposób rozwiązania takiego problemu.
Go to the top of the page
+Quote Post
ukaszq
post
Post #7





Grupa: Zarejestrowani
Postów: 128
Pomógł: 0
Dołączył: 8.08.2007

Ostrzeżenie: (10%)
X----


No moze rzeczywiscie.
Ale wiesz... ja tych wyników mam mieć np 600. Zrobilem petle ktora ma generowac takie liczby z przedzialu np 20,0 do 21,6 aby przy sumie 600 wyników srednia dala np 20,9.
Nie wiem jak to rozwizac...
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #8





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


  1. <?php
  2. $target_average = 15;
  3. $count = 100;
  4. $min = 10;
  5. $max = 20;
  6. $precision = 3;
  7.  
  8. // ------------
  9. $divider = pow( 10, $precision );
  10. $generator = new AvgGenerator( $target_average, $min, $max, $precision );
  11. $numbers = $generator->generate( $count );
  12.  
  13. stats( $numbers, $precision );
  14.  
  15.  
  16. function stats( $numbers, $precision )
  17. {
  18. $sum = 0.0;
  19. $min = reset( $numbers );
  20. $max = reset( $numbers );
  21. foreach ( $numbers as $n )
  22. {
  23. $sum += $n;
  24. if ( $n < $min )
  25. {
  26. $min = $n;
  27. }
  28.  
  29. if ( $n > $max )
  30. {
  31. $max = $n;
  32. }
  33. }
  34.  
  35. $c = count( $numbers );
  36. $average = $sum / (float)$c;
  37. //printf( "count: %.{$precision}d, average: %.{$precision}f, min: %.{$precision}f, max: %.{$precision}f\n", $c, $average, $min, $max );
  38. }
  39.  
  40. class AvgGenerator
  41. {
  42. private $target_average;
  43. private $min;
  44. private $max;
  45. private $precision;
  46.  
  47. public function __construct( $target_average, $min, $max, $precision )
  48. {
  49. $this->target_average = $target_average;
  50. $this->min = $min;
  51. $this->max = $max;
  52. $this->precision = $precision;
  53. }
  54.  
  55. public function generate( $count )
  56. {
  57. $currentAverage = 0.0;
  58. $currentSum = 0.0;
  59. $numbers = array();
  60. $divider = pow( 10, $this->precision );
  61. $done = 0;
  62. $left = $count;
  63. for ( $i = 0; $i < $count; $i++ )
  64. {
  65. if ( $this->overTargetAverage( $currentAverage ) )
  66. {
  67. $currentMax = $this->countCurrentMax( $currentAverage, $done, $left );
  68. $currentMin = $this->min;
  69.  
  70. }
  71. else
  72. {
  73. $currentMin = $this->countCurrentMin( $currentAverage, $done, $left );
  74. $currentMax = $this->max;
  75. }
  76.  
  77. $done = $i + 1;
  78. $left = $count - $done;
  79. $nextNumber = $this->nextRandomFloat( $currentMin, $currentMax, $divider );
  80. $numbers[] = $nextNumber;
  81. $currentSum += $nextNumber;
  82. $currentAverage = $currentSum / $done;
  83. // printf( "[%d] x = %.3f ; sum = %.3f ; avg = %.3f ; tavg = %.3f<br />", $done, $nextNumber, $currentSum, $currentAverage, $this->target_average );
  84. printf( "%d; %.3f\n", $done, $nextNumber);
  85. }
  86.  
  87. return $numbers;
  88. }
  89.  
  90.  
  91. private function nextRandomFloat( $min, $max, $divider )
  92. {
  93.  
  94. $min = $min * $divider;
  95. $max = $max * $divider;
  96. $x = (float)(rand( 0, $max - $min ) + $min ) / (float)$divider;
  97.  
  98. return $x;
  99. }
  100. private function countCurrentMax( $currentAverage, $done, $left )
  101. {
  102. $targetSum = $this->target_average * ( $done + $left );
  103. $currentSum = $currentAverage * $done + $this->min * ( $left - 1 ); // minimum sum that we may get (excluding current number
  104. $diffSum = $targetSum - $currentSum;
  105. if ( $diffSum < $this->max )
  106. {
  107. return $diffSum;
  108. }
  109. else
  110. {
  111. return $this->max;
  112. }
  113.  
  114. }
  115. private function countCurrentMin( $currentAverage, $done, $left )
  116. {
  117. $targetSum = $this->target_average * ( $done + $left );
  118. $currentSum = $currentAverage * $done + $this->max * ( $left - 1 ); // minimum sum that we may get (excluding current number
  119. $diffSum = $targetSum - $currentSum;
  120. if ( $diffSum > $this->min )
  121. {
  122. return $diffSum;
  123. }
  124. else
  125. {
  126. return $this->min;
  127. }
  128.  
  129. }
  130.  
  131. private function overTargetAverage( $currentAverage )
  132. {
  133. return $currentAverage > $this->target_average;
  134. }
  135.  
  136. private function underTargetAverage( $currentAverage )
  137. {
  138. return $currentAverage < $this->target_average;
  139. }
  140.  
  141.  
  142. }
  143. ?>


+ Trzyma sie sredniej,
- czasami przekracza nieznacznie zalozone min i max, ale nie mam teraz czasu zeby to dokladnie przebadac
- no i wada: koncowe wartosci czesto sa na sile dobierane zeby sie w sredniej zmiescic, np. 5% ostatnich wartosci to np. min lub tylko max

Wynik:
http://sunki.quickshareit.com/share/picture2af6b4.png

dla [10, 20] i sredniej 15 (czyli tak jak w kodzie)
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 16.09.2025 - 17:41