I need to generate a random number within a given range. The number must be different for every new month of the year, and it should not be the same (although theoretically it is possible) as the number generated the year before for that given month.
I was thinking of using the php rand($min, $max) function in conjunction with date("w"), I am struggling with the part where I need to get different results for every year.
To illustrate what I mean, check this:
$numbers = range(1, 100); //our random array
echo $numbers[date("w")]; //date("w") returns number of week
There are 2 problems here: 1) it is not really random, 2) the number will be the same every year and 3) it does not reflect the whole size of the array as date("w") returns a number between 1 and 52.
Do you think this is accomplishable in pure PHP? Or do I need to make a cronjob for this?
Thank you for any help.
You could use every month the same number in the seed. Just to be clear the seed in the function srand ([ int $seed ] ).
You can do something like this:
srand(100);
echo rand();
and every time it returns the same number. So every month you can do something like this:
$min = 1;
$max = 100;
date_default_timezone_set('UTC');
$seed = date('Ym'); // it is the date as an integer
srand($seed);
echo rand($min, $max);
Pay attention to set the default time zone. If you don't, the result will depend to the server configuration.
-- UPDATE --
As #StevenSmith and #axiac stated you're not 100% sure the random generated number is unique.
In other words this means that wider the range (min-max) higher the probability you'll have every time a different number.
Use date('Ym') to generate an unique identifier for each (year, month) combination, use this value to initialize the pseudo-random generator's engine then generate one random number:
srand(date('Ym'));
$value = rand(1, 100);
Adjust the second line to match your needs. Now it generates an integer number between (and including) 1 and 100.
The value returned by date('Ym') is the same during a month. Every time you call srand() with a certain argument, the pseudo-random generator is reinitialized using that value and then it produces the same sequence of pseudo-random numbers when rand() is invoked (several times).
This ensures the generation of the same value for you during the entire month. During the next month and during the same month of the subsequent years the pseudo-random number generator is initialized with a different value and it generates a different sequence of pseudo-random numbers.
Depending on the values you use in your call to rand(), it might happen that the value returned by it this month is returned again in a different month. Use a large range for its $min and $max arguments to minimize this possibility.
You could generate a random number, select the closest multiple of 12, and then add the current month number.
For example, if the random number is 616, the closest multiple of 12 is 612. Add 0 (since it's currently January) giving you a final answer of 612. This will ensure that the number is unique for each month.
Related
I'm trying to calculate a sort or "daily random number" in a range, wich can't be guessed, for each user in our site but can't figure out how to do it.
I don't want a random number either, it must be a calculated number in PHP, not an additional database field or anything similar.
I tought at a function who can take the user's ID and the day of year and calculate this number.
Example:
USERID: 12345, Range: 0-7 (constant values for every user)
DayOfYear: 250 (change every day)
Then something like: ((12345 + 250) MODULO 8) (so I've range from 0 to 7 for each user). The problem is that the same number will come out every 8 days in a loop that user will find very fast.
Each user don't necessarly need a different number for every day, even the same number would be OK for a few days but not all users must have the same number. Also, most important, no loop scenario, so user can't guess his his daily number.
Thank you for your help.
There are so many answers to this question and none would be the best ... but I'm in a funny mood:
$id = hexdec(substr(md5($userId . date('z')), 0, 3)) % 8;
Use the md5-function to get a hex-string from a string. Then use a part of this string to calculate the mod 8.
For the next 10 days the id will be 5,7,5,3,6,0,2,0,2,4 when using your user id
But to guess a number between 0 and 7 isn't so hard, don't uses this for security ...
I have been struggling with a problem for a while now.
Namely I need to generate a number in range 1 - 50 using a date. What I mean is if I run a some piece of code withing a specific date, it should produce me the same number for that day. If the date changes it should produce me a different number in defined range and preferably that does not show pattern with numbers generated in previous dates (constantly rising for example). I believe it can't be done with some mathematical linear function since the graph of that function would always produce me a pattern how the numbers are changing in time. Perhaps there is some function that is used in cryptography that would help?
seed your random generator via srand
If the input number should does not change for the day then your random returns will be predictable for that day.
You can use the number of days since 1970, or the day of the month as a seed value
Just use a hashing algorithm on your date convert it to a number and define an upper bound using modulo e.g.:
$yournumber = hexdec( sha1($date) ) % 50;
If I have a truely random number and I use mt_srand to seed mt_rand with the truly random number before I use mt_rand, will this mean the result of mt_rand is now also truly random rather than pseudorandom?
In otherwords, would the below code produce a truly random integer between the given minimum and maximum value
function RandomInteger($min, $max)
{
$trueRandomNumber = GetTrueRandomNumber();
mt_srand($trueRandomNumber);
return mt_rand($min, $max);
}
Secondly, should the true random number used to seed mt_srand be of 32 integers?
Looking at your code, my guess is that you are getting some value from GetTrueRandomNumber() (code is missing) but then you want that number to be in a specific range of values. So you are taking that output and inputting it into mt_rand() because it has a method of generating a number in a specific range.
While not a direct answer to your question, a better solution is to first figure out the range of values you want (i.e. as if the input $min was 0 and $max was $max - $min). Then, figure out the maximum number of bits that are required to obtain a value in that range. Then, extract that number of bits from the output of GetTrueRandomNumber(). If the value is within the range, return the number + the original $min value. If the value isn't within the range, get more bits of data. The key is to throw away bits until you get some in the desired range.
If need example source code for this, try:
http://barebonescms.com/documentation/csprng/
You should be able to put something similar together. I'd be wary of using mt_rand() for anything like this but it might be okay in this very specific instance. It depends on what you plan on using it for. It also depends highly on how well distributed the first number from Mersenne Twister actually is. I don't think anyone's done any work on that. MT is intended to be seeded one time - who knows what the distribution pattern is for repeatedly seeding it. Also, if other code uses mt_rand(), you risk exposure of your function's state based on later values that might get generated by later mt_rand() calls.
No. Mersenne twisters are always pseudorandom. The seed only determines where in the sequence it starts.
I have an array of 52 different values that I can pass through a class to get a number in return.
$array = array("A","B","C","D"...);
Each value passed through the class gives a different number that can be either positive or negative.
The numbers are not equally distributed but are sorted in natural order.
E.g.
$myclass->calculate("A"); // 2.3
$myclass->calculate("B"); // 0.25
$myclass->calculate("C"); // -1.3
$myclass->calculate("D"); // -6
I want to get the last value that return a number >= 0.20 (in the example would be "B").
This should be done in the minimum number of "class invocation" to avoid time wasting.
I thought something like: divide $array in 2 pieces and calculate the number I get, if it is >= 20, then split the last part of $array in other 2 smaller pieces and so on. But I don't know if this would work.
How would you solve this?
Thanks in advance.
What you're describing is called a binary search, but it won't really work for this use case, because you aren't searching for a known value. Rather, you're searching for the value that is the lowest number >= 0.2 in a set where the exact value 0.2 may not exist (if it were guaranteed to exist, then you could do a binary search for 0.2, and then your letter would simply be n - 1; n != 0).
If your range is always A-Z, a simple linear search would definitely be the easiest method. The time savings on a data set of 26 elements for using a more efficient method is negligible (talking milliseconds here), compared to implementation time.
Edit: I see you actually mentioned 52 elements, not 26. My point is still the same, though. The number of elements would need to be in the tens of thousands or more for there to be any significant savings, unless you are performing this operation in a tight loop.
I'm stuck with a small issue and don't want to generate my own algo for random number.
I've to Display 'word of the day' on website, it has to change only once per day and all data is stored in XML. At pageload I read xml file by simpleXml Parser in php and then generate a random number between 0, length of array and output a term + definition.
But i dont want it to change with every refresh, nor do I want to save it on server in database.
So how can I generate a random number between 0 to N, which would give same value for a span of 24 hours.
Just set the current date as Seed without hours, minutes and seconds.
srand(mktime(0, 0, 0));
$wordIndex = rand(0, $wordCount);
It will return the same number for one Day.
Option 1: No random numbers, just increase the index by one every day. It will look random enough since no one knows your file. If that is not good enough, randomize the input file (shuffle it once and safe it out again).
Option 2: Use today's date as the seed for the random number generator.
<?
srand(date("ymd"));
echo rand();
?>
If you dont want to store it, then use something, that is connected to daily cycle, for example, the date, or weekday.