Setting probability of getting a random number 1 or 2 - php

Is there a way to set a probability control on getting a random value either 1 or 2? Suppose if I want more than 70% of the time it should be 1 and only 30% should be the chance of getting 2 in rand(1,2). Is it possible?

Generate a number between 1 and 10, then if the number is greater than 7, return 2, else return 1
x = rand(1, 10);
if(x > 7){
return 2;
}
else {
return 1;
}
You will have 70% and 30% of chance to get the number you want

Why don't you generate a uniformly distributed random number and then filter the number with an if?
int x,r;
r=rand() % 100; // r in the range 0 to 99
if(r<=70){x=1;}
else{x=2;}

This should do the trick:
function yourrand($prob) {
$r = rand();
if ($r < $prob) { return 1; }
else { return 2; }
}

Related

PHP random numbers frequency of occurrence

In PHP I want to generate random numbers from 1 to 10 in a loop.
So for example:
$factor="1"; // this will be changed in another area
for ($i=0;$i<10;$i++) {
if ($factor=="1") {$output = rand(1,10);}
else if ($factor=="2") {$output = rand(1,10);}
else {$output = rand(1,10);}
}
Now to explain this - In result I want to receive 10 random numbers, but when $factor = "2", in that case I want to receive numbers from 6 to 10 more frequently as lower numbers.
It means, from 10 numbers I need to have 80% higher random numbers (it means larger than 5) and in 20% lower numbers (5 or lower).
E.g. 1,2,6,7,8,9,7,9,8,6 (1,2 are the only lower numbers = 20%, the rest are higher = 80)
If the $factor will change, then I want to change the percentage, in that case for example 40% lower numbers, 60% higher numbers.
The idea I have is to put each output in the loop to an array, then check each result and somehow calculate, if there is no 80% of larger numbers, then get random numbers again for those, but this seems to be an overkill.
Is there a simplier solution?
Let's go with the percentages you mention and first generate a random number between 1 and 100. Then the lower number, 1 to 20, have to represent outputs 1 to 5 and the higher numbers, 21 to 100, have to represent output 6 to 10. In PHP that would look like this:
function HighMoreOften()
{
$percentage = rand(1, 100);
if ($percentage <= 20) {
return rand(1, 5);
} else {
return rand(6, 10);
}
}
That should do the trick. You can also convert the percentage you got into the output, this would probably be slightly faster:
function HighMoreOften()
{
$percentage = rand(1, 100);
if ($percentage <= 20) {
return ceil($percentage / 5);
} else {
return 6 + ceil(($percentage - 20) / 20);
}
}
but personally I think the first version is easier to understand and change.
To change frequency you gonna need an array of numbers. And a sum to this direction. frequency is the relation of something between an array of things.
$t = 0;
// $factor = 1; // let's say that this means 20%
$factor = 2; // let's say that this means 40%
if ($factor === 1) {
for ($i = 1; $i <= 80; $i++) {
$t += rand(1,10);
}
for ($i = 1; $i <= 20; $i++) {
$t += rand(6,10);
}
} else if ($factor === 2) {
for ($i = 1; $i <= 60; $i++) {
$t += rand(1,10);
}
for ($i = 1; $i <= 40; $i++) {
$t += rand(6,10);
}
} else {
for ($i = 1; $i <= 100; $i++) {
$t += rand(1,10);
}
}
echo round(($t/100), 0);
Something like that! :)
I came with a very simple (maybe creepy) solution, but this works as I wanted:
echo print_r(generate("2"));
function generate($factor) {
$nums=array();
for ($i=0;$i<10;$i++) {
if ($i<$factor) {$rnd = rand(1,5);}
else {$rnd = rand(6,10);}
array_push($nums,$rnd);
}
return $nums;
}
I can also shuffle the final array results, as the lower numbers will be on the beginning always, but in my case it doesn't matter.

PHP random INT with evenly distributed order of magnitude results

PHP rand(min, max) between 1 and 9999 gives almost all results with 4 digits (because there are ~90% of the numbers with 4 digits). So, if I ran it 1000 times, roughly ~90% of them will probably have 4 digits.
Is there a way to generate a random INT from 1 to 9999 and that the output number have the same chance of having 1, 2, 3 or 4 digits without doing it manually?
By doing it manually I mean like this:
$digits = rand(1, 4);
$num = '';
for($i = 0; $i < $digits; $i++){
$num .= rand(0, 9);
}
$final = intval($num);
So, if I ran it 1000 times, roughly ~90% of them will probably have 4 digits.
That's exactly how uniform distributions work. There's no out of the box function to do what you're after, so you have to make some statistics magic.
What I'm thinking of is: generate a random number between 0 and 1. If it's between 0 and .25, generate another random number between 0 and 9. If it's between .25 and .5, generate another random number between 10 and 99, and so on and so forth. Then, you'd have 1/4 chance of getting each order of magnitude.
This will obviously have a bias towards the lower numbers though, since there are less of them. For example, 1 has a 25% / 10 = 2.5% chance, while 1001 has a 25% / 8998 = 0.00277% chance.
It'd go something like this:
<?php
$initial = rand(0, 100)/100;
if ($initial < .25) {
$random = rand(0, 9);
}
elseif ($initial < .5) {
$random = rand(10, 99);
}
elseif ($initial < .75) {
$random = rand(100, 999);
}
elseif ($initial >= .75) {
$random = rand(1000, 9999);
}
var_dump($random);
Demo

Reduce number to single digit using recurssion

$result = reduce($number);
function reduce($number) {
$new_number = 0;
if($number < 10) {
return $number;
}
$q = floor($number / 10 );
$r = $number % 10;
$new_number = $q + $r;
if($new_number <= 9) {
return $new_number;
}
else {
reduce($new_number);
}
}
I want to sum the numbers by its digits
For example, if i pass 10, it should return 1+0 = 1
This works if i pass 10
But not working when i pass 100.
This should work for you:
Just split your number into an array with str_split() and then use array_sum() to add all digits together.
echo array_sum(str_split($number));
EDIT:
If you don't want the checksum, but go down to a single digit, you also don't have to write that much code. Just call the function over and over again until the array_sum() is equal or less than 9.
function reduceToOneSingleDigit($result) {
$result = str_split($result);
while(array_sum($result) > 9)
return reduceToOneSingleDigit(array_sum($result));
return array_sum($result);
}
echo reduceToOneSingleDigit(99);
Just too much code, take a look at next one
print sum(125); // 8
// 5 12
// 2 1
// 1 + ~>0
function findSum($num)
{
if($num == 0)
return 0;
return $num%10 + findSum(floor($num/10));
}
so, even 100000 or 000001 will be 1, works just as U want, but it will have troubles if the paramater will be 0001000
You are missing the word return near the end. It should look like this:
return reduce($new_number);

Creating a 5 star product review with PHP

I'm working on a 5 stars products review for a website using php and MySQL, everything works great except my total stars,
When the review is submitted the customer can only add from 1 to 5 stars (no .5) then I'm summing the rating of each review and dividing it by the number of reviews. Now the proble is I need to get either 1, 1.5, 2, 2.5 and so on and sometimes I'll get something like 3.66768748.
How can I round the number so that if it's below if it's more that .5 it will be the ceil, if it's .5 it stays as is and if it's less than .5 it will floor it?
Is there a built in function that I can use for this?
Thank you in advance!
The following function will round to whichever is closest - the next lowest integer, the next highest integer, or the halfway point between them.
function half_star_round($input) {
$frac = $input - floor($input);
if($frac < 0.25) {
return floor($input);
} else if($frac >= 0.75) {
return ceil($input);
} else {
return floor($input) + 0.5;
}
}
This works. Pass the value you want to be rounded to in the second arg. In your case 0.5
function roundTo($value, $roundTo = 1) {
$rounded = round($value); // 4
$roundToComparer = $roundTo / 2;
if ($value < $rounded) { // rounded to ceiling
if (($rounded - $roundToComparer) > $value) {
$rounded = $rounded - $roundTo;
}
} else { // rounded to floor
if (($rounded + $roundToComparer) < $value) {
$rounded = $rounded + $roundTo;
}
}
return $rounded;
}
$rating = 3.66768748;
echo roundTo($rating, 0.5);
Take the sum of the reviews
Divide by the total reviews
Multiply by two
Round
Divide by two
Php proveide round function for that.
http://php.net/manual/en/function.round.php

PHP Random numbers

I would like to draw a random number from the interval 1,49 but I would like to add a number as an exception ( let's say 44 ) , I cannot use round(rand(1,49)) .So I decided to make an array of 49 numbers ( 1-49) , unset[$aray[44]] and apply array_rand
Now I want to draw a number from the interval [$left,49] , how can I do that using the same array that I used before ?The array now misses value 44.
The function pick takes an array as an argument with all the numbers you have already picked. It will then pick a number between the start and the end that IS NOT in that array. It will add this number into that array and return the number.
function pick(&$picked, $start, $end) {
sort($picked);
if($start > $end - count($picked)) {
return false;
}
$pick = rand($start, $end - count($picked));
foreach($picked as $p) {
if($pick >= $p) {
$pick += 1;
} else {
break;
}
}
$picked[] = $pick;
return $pick;
}
This function will efficiently get a random number that is not in the array AND WILL NEVER INFINITELY RECURSE!
To use this like you want:
$array = array(44); // you have picked 44 for example
$num = pick($array, 1, 49); // get a random number between 1 and 49 that is not in $array
// $num will be a number between 1 and 49 that is not in $arrays
How the function works
Say you are getting a number between 1 and 10. And you have picked two numbers (e.g. 2 and 6). This will pick a number between 1 and (10 minus 2) using rand: rand(1, 8).
It will then go through each number that has been picked and check if the number is bigger.
For Example:
If rand(1, 8) returns 2.
It looks at 2 (it is >= then 2 so it increments and becomes 3)
It looks at 6 (it is not >= then 6 so it exits the loop)
The result is: 3
If rand(1, 8) returns 3
It looks at 2 (it is >= then 2 so it increments and becomes 4)
It looks at 6 (it is not >= then 6 so it exits the loop)
The result is 4
If rand(1, 8) returns 6
It looks at 2 (it is >= then 2 so it increments and becomes 7)
It looks at 6 (it is >= then 6 so it increments and becomes 8)
The result is: 8
If rand(1, 8) returns 8
It looks at 2 (it is >= then 2 so it increments and becomes 9)
It looks at 6 (it is >= then 6 so it increments and becomes 10)
The result is: 10
Therefore a random number between 1 and 10 is returned and it will not be 2 or 6.
I implemented this a long time ago to randomly place mines in a 2-dimensional array (because I wanted random mines, but I wanted to guarantee the number of mines on the field to be a certain number)
Why not just check your exceptions:
function getRand($min, $max) {
$exceptions = array(44, 23);
do {
$rand = mt_rand($min, $max);
} while (in_array($rand, $exceptions));
return $rand;
}
Note that this could result in an infinite loop if you provide a min and max that force mt_rand to return an exception character. So if you call getRand(44,44);, while meaningless, will result in an infinite loop... (And you can avoid the infinite loop with a bit of logic in the function (checking that there is at least one non-exception value in the range $min to $max)...
The other option, would be to build the array with a loop:
function getRand($min, $max) {
$actualMin = min($min, $max);
$actualMax = max($min, $max);
$values = array();
$exceptions = array(44, 23);
for ($i = $actualMin; $i <= $actualMax; $i++) {
if (in_array($i, $exceptions)) {
continue;
}
$values[] = $i;
}
return $values[array_rand($values)];
}
The simplest solution would be to just search for a random number from min to max - number of exceptions. Then just add 1 to the result for each exception lower than the result.
function getRandom($min, $max)
{
$exceptions = array(23, 44); // Keep them sorted or you have to do sort() every time
$random = rand($min, $max - count($exceptions));
foreach ($exceptions as $ex)
{
if ($ex > $random) break;
++$random;
}
return $random;
}
Runtime should be O(1+n) with n being the number of exceptions lower than the result.

Categories