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
dr_bonzo
post
Post #2





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

Posty w temacie


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: 11.10.2025 - 11:37