mt_rand and rand not working (PHP) - php

I am having a problem where by when I try and generate numbers randomly with either mt_rand or rand (on a larger scale) I get no result at all. This used to work fine on my server but there seems to be issues now and I am unsure why.
<?php
echo 'Your number is: '.rand(0, 99999999999999999999);
?>
Where as it I update it to something like (using a 9 digit number):
<?php
echo 'Your number is: '.rand(0, 999999999);
?>
the lower example will work fine. I have recently changed my server version PHP 7.0. Is there a way to increase the maximum number or a better way to be doing this? Thanks.

On both 32-bit and 64-bit systems, the number 99999999999999999999 is too large to be represented as an integer in PHP 7, so it becomes a float.
However, mt_rand() takes two integers. Because 99999999999999999999 is too large to be an integer, when you pass it to the function, PHP 7 throws an error, because it cannot be safely converted. You didn't get this error for 999999999, because it's small enough to be an integer.
Anyway, your current code probably isn't doing that you want under PHP 5: 99999999999999999999 is being silently converted to 7766279631452241920 on 64-bit systems, and something else on 32-bit systems. So you're not getting the full range of random numbers. You wrote rand(0, 99999999999999999999), but you're actually getting rand(0, 7766279631452241920).
If you just want a random number from the widest possible range, try this:
<?php
echo 'Your number is: '.rand(0, PHP_INT_MAX);
?>
PHP_INT_MAX is a constant containing the largest possible integer (which will be different depending on whether you're on 32-bit or 64-bit). So, doing this will always give you the widest possible range of random positive numbers from that function.

To run the code in php 7 you have to typecast
<?php
echo 'Your number is: '.rand(0,(int) 99999999999999999999);
?>

Microtime generated random everytime.
function microtimeRand( $min, $max ) {
$microtimeInt = intval( microtime( true ) * 100 );
$microtimeInt = $microtimeInt % ($max - $min);
$microtimeInt += $min;
return $microtimeInt;
}

Related

Why strlen doesn't work in a paticular digit

I made this function. It seemed it's working but when it comes to 20 digits number, the return value was 19. I'm wondering why this problem happen..
My function
function sumDigits($n) {
return strlen($n);
}
echo sumDigits(100); //3
echo sumDigits(1000); //4
echo sumDigits(12345); //5
echo sumDigits(1000000000); //10
echo sumDigits(145874589632); //12
echo sumDigits(0); //1
echo sumDigits(12345698745254856320); //19 <-- Why not 20?
Can you please somebody explain for me?
Thank you so much.
First, I would point out that the name of your function is misleading, as you are not really summing the values of the digits, but are counting the digits. So I would call your function countDigits instead of sumDigits.
The reason why it doesn't work for large numbers, is that the string representation will switch to scientific notation, so you're actually getting the length of "1.2345698745255E+19" not of "12345698745254856320"
If you are only interested in integers, you will get better results with the logarithm:
function countDigits($n) {
return ceil(log10($n));
}
For numbers that have decimals, there is no good solution, since the precision of 64-bit floating pointing point numbers is limited to about 16 significant digits, so even if you provide more digits, the trailing decimals will be dropped -- this has nothing to do with your function, but with the precision of the number itself. For instance, you'll find that these two literals are equal:
if (1.123456789123456789123456789 == 1.12345678912345678) echo "equal";
Because you function parameter is an integer, exceeding the limit.
If you dump it, it actually shows the following:
1.2345698745255E+19 - which is 19 letters.
If you would do the following, it will return 20 - mind the quotes, which declares the input as string.
echo sumDigits("12345698745254856320"); //19 <-- Why not 20? -> now will be 20
As per documentation, strlen() expects a string so a cast happens. With default settings you get 1.2345698745255E+19:
var_dump((string)12345698745254856320);
string(19) "1.2345698745255E+19"
The root issue is that PHP converts your integer literal to float because it exceeds PHP_INT_MAX so it cannot be represented as integer:
var_dump(12345698745254856320, PHP_INT_MAX);
In 64-bit PHP:
float(1.2345698745254857E+19)
int(9223372036854775807)
You could change display settings to avoid E notation but you've already lost precision at this point.
Computer languages that store integers as a fixed amount of bytes do not allow arbitrary precision. Your best chance is to switch to strings:
var_dump('12345698745254856320', strlen('12345698745254856320'));
string(20) "12345698745254856320"
int(20)
... and optionally use an arbitrary precision library such as BCMath or GMP if you need actual maths.
It's also important to consider that this kind of issues is sometimes a symptom that your input data is not really meant to be an integer but just a very long digit-only string.

php only show decimal place if have fraction

I set int data type in mysql database but it not showing decimal place like 10.20
Then I set decimal(10,5) it show five decimal place with all number thought it not necessary like 10.00000.
I want to show decimal places only if have fraction
like 10.25455 = 10.25455 and 10 = 10 but it showing 10 = 10.00000
how to solve this
You can use PHP round function.
http://php.net/manual/en/function.round.php
PHP Code:
<?php
echo round(10.25455, 5); // outputs: 10.25455
echo '<br/>';
echo round(10.00000, 5); // outputs: 10
Just add 0!
echo 10.25455 + 0;
echo 10.00000 + 0;
Output:
10.25455
10
Use decimal as a field type. Then in PHP use round(); function.
There is no datatype in mysql that supports your requirement. In fact, that is not how computers work. A number is either an int or a float.
You might want to use varchar instead, and cast to the right data type in php, but it might cause performance overhead. It is indeed a weird data type requirement. If you must go this route, consider adding an extra column for flagging data type.
echo floatval($value);
will do the trick.

What is PHP's mt_rand() minimum value and how to calculate 32 bit interger on 32 bit Linux box

What is the minimum value allowed for mt_rand()? Is it the same value for 32 bit and 64 bit machines? How could I generate a 32 bit integer using mt_rand() (note that it doesn't need to be highly random)?
BACKGROUND WHY I AM ASKING: I have a 64 bit development physical server and a 32 bit production VPS. Just realized the production server was not generating PKs spanning the full range. To figure out what is going on, I ran the following script. The 64 bit machine never (or at least I've never witnessed) matches, but the 32 bit matches about 50% of the time.
<?php
date_default_timezone_set('America/Los_Angeles');
ini_set('display_errors', 1);
error_reporting(E_ALL);
$count=0;
for ($i = 0; $i <= 10000; $i++) {
$rand=2147483648+mt_rand(-2147483647,2147483647); //Spans 1 to 4294967295 where 0 is reserved
if($rand==2147483649){$count++;}
}
echo('mt_getrandmax()='.mt_getrandmax().' count='.$count);
output
mt_getrandmax()=2147483647 count=5034
TL;DR: To get a random integer in the full range of possible integers, use:
function random_integer() {
$min = defined('PHP_INT_MIN') ? PHP_INT_MIN : (-PHP_INT_MAX-1);
return mt_rand($min, -1) + mt_rand(0, PHP_INT_MAX);
}
For PHP 7, you can use random_int().
Under the hood (1, 2), PHP is doing this:
$number = random_number_between_0_and_0x7FFFFFFF_using_Mersenne_Twister;
$number = $min + (($max - $min + 1.0) * ($number / (0x7FFFFFFF + 1.0)));
Notice $max - $min. When max is set to the top end and min is anything negative, an overflow occurs. Therefore, the maximum range is PHP_INT_MAX. If your maximum value is PHP_INT_MAX, then your minimum is necessarily 0.
Now for the back story. PHP implements the 32-bit Mersenne Twister algorithm. This gives us random integers between [0, and 2^31-1). If you ask for any other range, PHP scales that number using a simple binning function. That binning function includes a subtraction that can lead to overflow, and this problem.
Thus if you want to get a range larger than could be represented by an integer in PHP, you have to add intervals together, like so:
mt_rand(PHP_INT_MIN, -1) + mt_rand(0, PHP_INT_MAX);
Note that PHP_INT_MIN is available since PHP 7, so you'll need to calculate a suitable minimum for your environment before then.
As an aside, notice that 2^31-1 is what getrandmax() returns. People mistakenly believe that on a 64-bit machine getrandmax() will return 2^63-1. That's not true. getrandmax() returns the maximum integer the algorithm will return, which is always 2^31-1.
You can generate a 32 bit integer like this:
$rand = unpack("l", openssl_random_pseudo_bytes(4));
This is a problem that is noted in the PHP docs over here
This works fine on 64 bit Linux:
<?php
printf ("%08x\n", mt_rand (0, 0xFFFFFFFF));
?>
but on our 32 bit Linux development server, it's always yielding 00000000.
On that same machine, this:
<?php
printf ("%08x\n", mt_rand (0, 0xFFFFFFF0));
?>
seems to always yield either 00000000 or a number in the range fffffff2 to ffffffff. This:
<?php
printf ("%08x\n", mt_rand (0, 0xFFFFFF00));
?>
gives numbers where the last two digits vary, and so on through at least 0xF0000000.
However, this:
<?php
printf ("%08x\n", mt_rand (0, 0x7FFFFFFF));
?>
works fine
A bug report is added here.
There has been no word whether PHP is fixing this yet.
In the meantime you can use the mt_rand function between the max_rand and you should be fine
Example Usage
$rand=mt_rand(1,2147483647)+mt_rand(0,2147483647);

Random Number: converting JavaScript to PHP

I have the following line of code in javascript:
(Math.random() + "") * 1000000000000000000
which generates numbers like:
350303159372528000
I tried the same thing in PHP with this:
rand()*1000000000000000000
Which returns:
2.272e+21
I need to use PHP as the number generated will be stored as a SESSION variable and will be used by JavaScript later on.
How do I get PHP to force the number to be an int rather than a float?
EDIT PHP seems to struggle with this.
Would it work if I just generated the rand number in PHP saved it to the SESSION and then done the multiplying by 1000000000000000000 in JavaScript?
How would I go about this?
I'd recommend calling
PHP_INT_MAX
To see if your PHP installation can handle an integar that large. I'm guessing it can't which is why it is knocking it down to scientific notation.
I'd suggest converting your result to an int:
intval(rand()*1000000000000000000)
That said, see Kolink and Jeremy1026 answers for precision issues. If you only need an unique identifier, see Truth's answer.
Update: if you're using strings to represent your numbers, don't want or can't use an arbitrary precision library, and don't stricly need perfecly fair random numbers, you could generate smaller numbers and concat them together:
strval(rand()*999999999 + 1) . strval(rand()*1000000000)
(The +1 is to avoid a leading zero in your result; note also that your number will never have a single digit, but every other number is possible)
For a random number with (exactly) 18 digits, you can also use str_pad in the 2nd part, to fill it with leading zeros:
strval(rand(100000000,999999999)) .
str_pad(strval(rand(0,999999999)), 9, "0", STR_PAD_LEFT)
If you need a unique identifier (which is what it looks like you're trying to do), please use PHP's uniqid() function.
floor() / ceil() / round() / (int) / intval() will convert the number to int.
Also, rand() takes two arguments. If ints are supplied - it will return an integer
And printf() should take care of printing in the format you wish (printf('%d', $int) should do the trick)
In the end I solved the issue like this:
<?php
error_reporting(0);
function RandNumber($e){
for($i=0;$i<$e;$i++){
$rand = $rand . rand(0, 9);
}
return $rand;
}
echo RandNumber(18);
// Outputs a 18 digit random number
?>

Is there something that's larger than any numbers in PHP?

I need to simulate a ∞ in PHP.
So that min(∞,$number) is always $number.
I suppose that, for integers, you could use PHP_INT_MAX , the following code :
var_dump(PHP_INT_MAX);
Gives this output, on my machine :
int 2147483647
But you have to be careful ; see Integer overflow (quoting) :
If PHP encounters a number beyond the
bounds of the integer type, it will
be interpreted as a float instead.
Also, an operation which results in a
number beyond the bounds of the
integer type will return a float
instead.
And, from the Floating point numbers documentation page :
The size of a float is
platform-dependent, although a maximum
of ~1.8e308 with a precision of
roughly 14 decimal digits is a common
value (the 64 bit IEEE format).
Considering the integer overflow, and depending on your case, using this kind of value might be a better (?) solution...
Use the constant PHP_INT_MAX.
http://php.net/manual/en/language.types.integer.php
You could potentially use the PHP_INT_MAX constant (click for PHP manual docs).
However, you may want to think about whether you really need to use it - it seems like a bit of an odd request.
PHP actually has a predefined constant for "infinity": INF. This isn't true infinity, but is essentially the largest float value possible. On 64-bit systems, the largest float is roughly equal to 1.8e308, so this is considered to be equal to infinity.
$inf = INF;
var_dump(min($inf,PHP_INT_MAX)); // outputs int(9223372036854775807)
var_dump(min($inf,1.79e308)); // outputs float(1.79E+308)
var_dump(min($inf,1.799e308)); // outputs float(INF)
var_dump(min($inf,1.8e308)); // outputs float(INF)
var_dump($inf === 1.8e308); // outputs bool(true)
Note, any number with a value larger than the maximum float value will be cast to INF. So therefore if we do, var_dump($inf === 1e50000);, this will also output true even though the maximum float is less than this.
I suppose, assuming this is an integer, you could use PHP_INT_MAX constant.
min($number, $number + 1) ??
In Perl you can use
$INF = 9**9E9;
which is larger than any value you can store in IEEE floating point numbers. And that really works as intended: any non-infinite number will be smaller than $INF:
$N < $INF
is true for any "normal" number $N.
Maybe you use it in PHP too?
min($number,$number) is always $number (also true for max() of course).
If your only concern is comparison function then yes, you can use array(), it will be always larger then any number
like
echo min(array(), 9999999999999999);
or
if (array() > 9999999999999999) {
echo 'array won';
} else {
echo 'number won';
}

Categories