Random Number Script

M

McKirahan

Papajo said:
Hi, This script will write a random number into a document write tag,
I've been trying to get it to write into a input form box outside the
javascript, any help is appreciated. Thanks Joe

http://web2jo.com/Work/Random_Temp.html

Will this help?

<html>
<head>
<title>Random.htm</title>
<script type="text/javascript">
function getRandomNum(lbound, ubound) {
var num = Math.floor(Math.random() * (ubound - lbound)) + lbound;
document.forms[0].text.value = num;
}
</script>
</script>
</head>
<body>
<form>
<input type="text" name="text" size="6" readonly>
<input type="button" value="Random"
onclick="getRandomNum(111111,999999)">
</form>
</body>
</html>
 
P

Papajo

I had to modify the script a little but it works great, Thanks Joe


<script type="text/javascript">
function getRandomNum(lbound, ubound) {
var num = (Math.floor(Math.random() * (ubound - lbound)) + lbound);
document.forms[0].text.value = num;
}
</script>
</head>
<body>
<form>
<input type="text" name="text" size="6" readonly>

<input type="button" value="Random"
onclick="getRandomNum(111111,999999)">
</form>
 
T

Thomas 'PointedEars' Lahn

McKirahan said:
Will this help?

Not really.
[...]
function getRandomNum(lbound, ubound) {
var num = Math.floor(Math.random() * (ubound - lbound)) + lbound;
document.forms[0].text.value = num;
}

- Let lbound be 1.
- Let ubound be 10.
- Let Math.random() return 0.99.
- That returns

Math.floor(0.99 * (10 - 1)) + 1
= Math.floor(8.91) + 1
= 8 + 1
= 9

Since Math.random() always returns something less than 1, it is not possible
that the result is 10. But remember: we are speaking of a random integer
in the _closed_ interval [x, y], that is, the bounds are included. If the
upper bound is y and y is an integer, the probability of returning y should
be greater than zero. Meaning that your algorithm computes a random
integer in the right-hand side open interval [x, y) which is not what was
specified.

This problem can be solved by using Math.round() instead of Math.floor() and
rounding a computed floating-point number. With

function getRandomNum(lbound, ubound)
{
return Math.round(Math.random() * (ubound - lbound) + lbound);
}

document.forms[0].text.value = getRandomNum(1, 10);

- Let lbound be 1.
- Let ubound be 10.
- Let Math.random() return 0.99.
- That returns

Math.round(0.99 * (10 - 1) + 1)
= Math.round(0.99 * 9 + 1)
= Math.round(8.91 + 1)
= Math.round(9.91)
= 10

- Let lbound be 1.
- Let ubound be 10.
- Let Math.random() return 0.01.
- That returns

Math.round(0.01 * (10 - 1) + 1)
= Math.round(0.01 * 9 + 1)
= Math.round(0.09 + 1)
= Math.round(1.09)
= 1

Since Math.random() will never return something less than 0, and always
something less than 1 (ECMAScript 3, 15.8.2.14), that algorithm is safe.


PointedEars
 
R

Randy Webb

Thomas 'PointedEars' Lahn said the following on 12/22/2005 3:40 PM:

Since Math.random() will never return something less than 0, and always
something less than 1 (ECMAScript 3, 15.8.2.14), that algorithm is safe.

Opera 6 is known to return 1 from Math.random()
 
B

bwucke

Thomas said:
McKirahan said:
Papajo said:
Will this help? Not really.
var num = Math.floor(Math.random() * (ubound - lbound)) + lbound;
document.forms[0].text.value = num;
Since Math.random() always returns something less than 1, it is not possible
that the result is 10. But remember: we are speaking of a random integer
in the _closed_ interval [x, y], that is, the bounds are included. If the
upper bound is y and y is an integer, the probability of returning y should
be greater than zero. Meaning that your algorithm computes a random
integer in the right-hand side open interval [x, y) which is not what was
specified.

This problem can be solved by using Math.round() instead of Math.floor() and
rounding a computed floating-point number.

Thanks to which you get the boundary values at half the probability as
the rest.
return Math.round(Math.random() * (ubound - lbound) + lbound);

Math.round(0.00 * (10 - 1) + 1) = Math.round(1.00) = 1
Math.round(0.055 * (10 - 1) + 1) = Math.round(1.495) = 1
Math.round(0.056 * (10 - 1) + 1) = Math.round(1.504) = 2
Math.round(0.166 * (10 - 1) + 1) = Math.round(2.494) = 2
Math.round(0.167 * (10 - 1) + 1) = Math.round(2.503) = 3

0.055-0 = 0.055 = 5.5%
0.166-0.056 0.11= 11%

It's much better to remain at the Math.floor approach and simply
randomize at one more than originally.

var num = Math.floor(Math.random() * (ubound - lbound + 1)) + lbound;
 
T

Thomas 'PointedEars' Lahn

Randy said:
Thomas 'PointedEars' Lahn said the following on 12/22/2005 3:40 PM:

Opera 6 is known to return 1 from Math.random()

OK, then a workaround is needed, something like

var r = Math.random();
if (r == 1)
{
r -= Math.pow(2, -53);
}


PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
McKirahan said:
http://web2jo.com/Work/Random_Temp.html
Will this help? Not really.
var num = Math.floor(Math.random() * (ubound - lbound)) + lbound;
document.forms[0].text.value = num;
Since Math.random() always returns something less than 1, it is not
possible that the result is 10. But remember: we are speaking of a
random integer in the _closed_ interval [x, y], that is, the bounds
are included. If the upper bound is y and y is an integer, the
probability of returning y should be greater than zero. Meaning that
your algorithm computes a random integer in the right-hand side open
interval [x, y) which is not what was specified.

This problem can be solved by using Math.round() instead of Math.floor()
and rounding a computed floating-point number.

Thanks to which you get the boundary values at half the probability as
the rest.

True (provisionally, see below), thank you for pointing out.
Math.round(0.00 * (10 - 1) + 1) = Math.round(1.00) = 1
Math.round(0.055 * (10 - 1) + 1) = Math.round(1.495) = 1
Math.round(0.056 * (10 - 1) + 1) = Math.round(1.504) = 2
Math.round(0.166 * (10 - 1) + 1) = Math.round(2.494) = 2
Math.round(0.167 * (10 - 1) + 1) = Math.round(2.503) = 3

0.055-0 = 0.055 = 5.5%
0.166-0.056 0.11= 11%

However, your reasoning is strange, to say the least.

My reasoning for the almost correct assumption you stated above is: There
are _about_ two times more reals in each of the intervals [x, y) with
x := 2z + 0.5, y := (2z + 1) + 0.5, and integer z in [0, 4], than in the
interval [a, b), with a := 0 and b := 0.5, or in the interval [c, d], with
c := 9.5 and d := 10. (You may note that there is exactly one more real in
[c, d] than in [a, b), which is one reason why the "_about_" is necessary.
Also note that I am speaking of reals when we are dealing with IEEE-754
floating-point numbers with limited precision.)
It's much better to remain at the Math.floor approach and simply
randomize at one more than originally.

var num = Math.floor(Math.random() * (ubound - lbound + 1)) + lbound;

Full ACK


PointedEars
 
R

Randy Webb

Thomas 'PointedEars' Lahn said the following on 12/22/2005 5:49 PM:
Randy Webb wrote:




OK, then a workaround is needed, something like

var r = Math.random();
if (r == 1)
{
r -= Math.pow(2, -53);
}

There is a solution on the web, I don't recall where, think it was
DAVAR's questionable FAQ site. IIRC, it looked something like
Math.random()%1 or something close. It was simple and involved %1. I
only remember it because I questioned the %1 and found out that some
Revisions of Opera 6 could return 1 from random()
 
T

Thomas 'PointedEars' Lahn

Thomas said:
[Math.round() is not suited for computing uniformly distributed random
integers in a closed interval since the boundary values are computed
at half the statistical probability of the rest]

My reasoning for the almost correct assumption you stated above is: There
are _about_ two times more reals in each of the intervals [x, y) with
x := 2z + 0.5, y := (2z + 1) + 0.5, and integer z in [0, 4],

Replacing the "2z" with "z" and "[0, 4]" with "[0, 8]". I would only
cover even numbers otherwise, which is still true, but not sufficient :)
than in the interval [a, b), with a := 0 and b := 0.5, or in the interval
[c, d], with c := 9.5 and d := 10. (You may note that there is exactly
one more real in [c, d] than in [a, b), which is one reason why the
"_about_" is necessary. Also note that I am speaking of reals when we
are dealing with IEEE-754 floating-point numbers with limited precision.)


PointedEars
 
B

bwucke

Thomas 'PointedEars' Lahn napisal(a):
Thomas said:
[Math.round() is not suited for computing uniformly distributed random
integers in a closed interval since the boundary values are computed
at half the statistical probability of the rest]
// x := z + 0.5, y := (z + 1) + 0.5, and integer z in [0, 8],
than in the interval [a, b), with a := 0 and b := 0.5, or in the interval
[c, d], with c := 9.5 and d := 10.

that's just extending and stating what I said. And maybe correcting
some computational errors (11% of what?). I try to avoid counting
floats, prefer to describe lengths of their ranges, because -one- float
more in a range really makes no difference when it comes to
probablility (practically, not matematically speaking.)

(is it a right approach? There's exactly as many floats in (1,10) as in
(10,100)... )

The .round() approach isn't wrong, you'd just need to adjust boundaries
for one more:
var num = Math.round(Math.random() * (ubound - lbound + 1) - 0.5) +
lbound;
which overly complicates things (plus rounding is more work than
truncating). Something that would survive the Opera bug would be
var num = Math.floor(Math.random() * (ubound - lbound + 0.9999999)) +
lbound;
Of course the upper bound will be shorter by a few integers, but see my
opinion above (instead of seeking a perfect solution, let's just use a
satisfactory one.)

(1 - (1/Infinity)) won't work it seems.
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Thu, 22 Dec
2005 21:40:49 local, seen in Thomas
'PointedEars' Lahn said:
This problem can be solved by using Math.round() instead of Math.floor() and
rounding a computed floating-point number. With

function getRandomNum(lbound, ubound)
{
return Math.round(Math.random() * (ubound - lbound) + lbound);
}


Unless specified otherwise, a random number should be evenly distributed
within its range.

That gives half-probability to the outer two values.

You refer people to the newsgroup FAQ often enough; you should read it
yourself to avoid silly mistakes such as that.


Several versions of Opera can return 1.0 from Math.random(); AIUI that
is sufficiently frequent that it should probably be protected against,
but not so frequent that it matters much what protection is used.

The simplest is to use Math.random()%1 as shown in a reference in the
FAQ, which also gives the functions that the OP need.


function Randum(N) { return (N*(Math.random()%1))|0 }
function RanSpan(MinV, MaxV) { return MinV + Randum(MaxV-MinV+1) }



If one believes that 1.0 should give the same result as 0.999999...,
it's silly to calculate Math.pow(2,53) and subtract; just return ubound.

function RandomA(N) { var Q // lbound=0
return (Q = Math.random()) == 1.0 ? N : Math.floor(N*Q) } // >= ??


If one believes that a result 1.0 should be ignored,

function RandomB(N) { var Q // lbound=0
while ( (Q = Math.random()) == 1.0 ) {}
return Math.floor(N*Q) }


Those seem to work but are only lightly tested, in IE.
 
J

John G Harris

However, your reasoning is strange, to say the least.

My reasoning for the almost correct assumption you stated above is: There
are _about_ two times more reals in each of the intervals [x, y) with
x := 2z + 0.5, y := (2z + 1) + 0.5, and integer z in [0, 4], than in the
interval [a, b), with a := 0 and b := 0.5, or in the interval [c, d], with
c := 9.5 and d := 10. (You may note that there is exactly one more real in
[c, d] than in [a, b), which is one reason why the "_about_" is necessary.
Also note that I am speaking of reals when we are dealing with IEEE-754
floating-point numbers with limited precision.)
<snip>

Talking about the number of real numbers in an interval can lead to very
misleading results.

There are exactly the same number of reals in [0.25..0.5) as in
[0.5..1.0), using the only definition of 'same number' that works.

There are also exactly the same number of IEEE floating point numbers in
[0.25..0.5) as in [0.5..1.0).

John
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated
Thu, 22 Dec 2005 20:04:56 local, seen in
Randy Webb said:
There is a solution on the web, I don't recall where, think it was
DAVAR's questionable FAQ site. IIRC, it looked something like
Math.random()%1 or something close. It was simple and involved %1. I
only remember it because I questioned the %1 and found out that some
Revisions of Opera 6 could return 1 from random()

If you use the newsgroup FAQ, you will be able to find it.

The matter was discussed here some while ago; but, I think, after the
arrival of LRN. It was certainly mentioned here last year.

<URL:http://www.merlyn.demon.co.uk/js-randm.htm#AfR> has it.
 
B

bwucke

Jasen said:
On 2005-12-23, (e-mail address removed) <[email protected]> wrote:
( There's exactly as many floats in (1,10) as in
not true true. (but the difference is not large)

this is because the density function is not reciprocal, but a staircase,

I know -that-
flat
between integer powers of two.

...and not ten. Thanks. Seems I didn't eradicate decimal thinking from
my mind as efficiently as I wished to.
there is however exactly as many in (1,2) as in (2,4) etc....

or (128,256). Thanks again for pointing out the mistake.
How does that relate to rand()?
floats are not the set of real numbers, neither are they the set of rational
numbers.

still, they approximate them sufficiently well as long as we keep
caveats in mind.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top