0

I have a wheel of fortune that spins, and has probability set for winning each prize that adds up to 100%. Once the quantity of a prize is met, ie, all of that prize is gone from stock, it sets the probability to 0 so you can't win it again. My problem then, is that the other values don't add up to 100. They always have to add up to 100 otherwise the wheel doesn't work.

I've got to the point of dividing all of the values by the total, rounding to two decimals and then adding them together, but i get 99 instead of 100. I've tried a few other ways of doing it and can never get to 100.

edit: My main problem seems to be that there is a 0.01% chance of winning 2 of the prizes. Dividing them by the total drops them to 0.000234234% or something similar, so when i multiply that by 100 then round that up to 2 decimals i'm getting 0.00% - but i can't think of any other way around it...

$jsonString = file_get_contents('wp-content/themes/supertheme/wheel_data.json');
$data = json_decode($jsonString, true);
echo '<pre>';
//print_r($data['segmentValuesArray'][0]['probability']);
echo '</pre>';

if ($prize1 <= 5){
    $prize1before = $data['segmentValuesArray'][0]['probability'];
    $data['segmentValuesArray'][0]['probability'] = 0;
}
if ($prize2 >= 5){
    $data['segmentValuesArray'][1]['probability'] = 0;
}
if ($prize3 >= 300){
    $data['segmentValuesArray'][2]['probability'] = 0;
}
if ($prize4 >= 500){
    $data['segmentValuesArray'][3]['probability'] = 0;
}
if ($prize5 >= 10){
    $data['segmentValuesArray'][4]['probability'] = 0;
}

$prize1total = $data['segmentValuesArray'][0]['probability'];
$prize2total = $data['segmentValuesArray'][1]['probability'];
$prize3total = $data['segmentValuesArray'][2]['probability'];
$prize4total = $data['segmentValuesArray'][3]['probability'];
$prize5total = $data['segmentValuesArray'][4]['probability'];

$total = $prize1total + $prize2total + $prize3total + $prize4total + $prize5total;
echo'<pre>';
print_r($total);
echo'<pre>';
$a = 0;
foreach($data['segmentValuesArray'] as $prize_array){
    if($prize_array['probability'] > 0){
        $a++;   
    }
}

$integer = $prize1before / $a;

$divided1 = $prize1total / $total;
$rounded1 = number_format((float)$divided1, 2, '.', '');
$full1 = $rounded1 * 100;

$divided2 = $prize2total / $total;
$rounded2 = number_format((float)$divided2, 2, '.', '');
$full2 = $rounded2 * 100 + $integer;

$divided3 = $prize3total / $total;
$rounded3 = number_format((float)$divided3, 2, '.', '');
$full3 = $rounded3 * 100 + $integer;

$divided4 = $prize4total / $total;
$rounded4 = number_format((float)$divided4, 2, '.', '');
$full4 = $rounded4 * 100 + $integer;

$divided5 = $prize5total / $total;
$rounded5 = number_format((float)$divided5, 2, '.', '');
$full5 = $rounded5 * 100 + $integer;

$newtotal = $full1 + $full2 + $full3 + $full4 + $full5;
echo'<pre>';
print_r($newtotal);
echo'<pre>';

$newJsonString = json_encode($data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
file_put_contents('wp-content/themes/supertheme/wheel_data.json', $newJsonString);
  • 1
    Floating point is an approximation. – Barmar Jun 18 '19 at 14:58
  • Hi Barmar. I've just read the post you say this is a duplicate of, although they are using floating point, they are not trying to do the same thing as me... –  Jun 18 '19 at 15:02
  • This is just a specific instance of a general problem with floating point. – Barmar Jun 18 '19 at 15:05
  • If the numbers don't add up to 100, add or substract 1 to one of the numbers to fix it. – Barmar Jun 18 '19 at 15:09
  • For instance, if you have 3 numbers 33, 33, 33, change one of them to 34. – Barmar Jun 18 '19 at 15:10
  • How are you getting 99 when you round to 2 decimal places. You should get somethng like 99.99. – Barmar Jun 18 '19 at 15:11
  • @Barmar this is indeed a solution - yet, if we had 33.49, 33.26, 33.25, we would like to add 1 to the *first* 33, not to any of the others. This can be done by calculating the array of percentages as floating points, then adding a second column with the decimal part (difference from the rounding), and sorting by decimal part descending. If the total is not 100, add 1 to all items starting from the first until the total is 100. A more rigorous solution (the result is the same) is using a variation on Bresenham's algorithm on the domains [0, total] vs [0, 100]. – LSerni Jun 18 '19 at 15:16
  • and @reigns1989, you *really*, *really* want to do this using arrays and cycles, not numeric suffixes added to your variables. Even if the number of prizes was fixed. – LSerni Jun 18 '19 at 15:18
  • My main problem seems to be that there is a 0.01% chance of winning 2 of the prizes. Dividing them by the total drops them to 0.000234234% or something similar, so when i multiply that by 100 then round that up to 2 decimals i'm getting 0.00% - but i can't think of any other way around it... –  Jun 18 '19 at 15:48

0 Answers0