Gmail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Message from discussion Math.random
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Johannes Baagoe  
View profile  
 More options Jun 25, 6:47 pm
Newsgroups: comp.lang.javascript
From: Johannes Baagoe <baa...@baagoe.com>
Date: Thu, 25 Jun 2009 17:47:00 -0500
Subject: Re: Math.random
Johannes Baagoe :

> I shall give it an attempt, though, in another post.

Here it is: introducing the Random object. Comments are welcome.

Synopsis :

  var r = new Random(seed1, seed2, ...);
  r.random(); // returns a "random" number in [0..1)

The constructor may be called with any number of seeds of any kind -
dates, strings, numbers, events, etc. (They are converted internally
to strings.)

You may, for instance, write things like

  r = new Random(
    new Date(),
    document.location.href,
    document.documentElement.clientWidth,
    document.documentElement.clientHeight
  );

which should make it rather unlikely that two users ever generate the same
sequence of numbers. (Assuming that the three last arguments make sense in
your environment, which should be checked beforehand, of course.)

new Random() with no arguments is equivalent to new Random(new Date()),
for convenience. Apart from this special case, two Random objects
constructed with the same arguments will yield the same sequence.

Other methods :

  reSeed(seed1, seed2, ...) alters the existing state by combining it with
  the new seeds. As with the constructor, if there is no seed at all, an
  implicit seed of new Date() is assumed. If called in an event handler,
  one of the seeds (most likely the only one) may be the event itself. The
  idea is to collect entropy, in order to make the sequence of "random"
  numbers truly unpredictable. No claim to cryptological security is made,
  however. (Also, while the implementation should, as far as I can see,
  work on any standard-compliant browser, I haven't tested it on anything
  but Firefox for Ubuntu. This is where I walk on the thinnest ice.)

  getState() returns the internal state of the generator, to allow replays.

  setState(state) resets the generator to a state saved with getState().

Code :

function Random() {
  var x = 123456789;
  var y = 362436069;
  var z =  21288629;
  var w =  14921776;
  var c =         0;

  var hash =  31415;

  function kiss32() {
    x += 545925293;
    x >>>= 0;

    y ^= y << 13;
    y ^= y >>> 17;
    y ^= y << 5;

    var t = z + w + c;
    z = w;
    c = t >>> 31;
    w = t & 0x7fffffff;

    return x + y + w >>> 0;
  }

  this.random = function() {
    return ((kiss32() >>> 5) / 134217728 + (kiss32() >>> 6)) / 67108864;
  }

  this.reSeed = function() {
    var seed = '';
    var i, arg, prop;

    if (arguments.length === 0) {
      this.reSeed(new Date());
    }

    for (i = 0; i < arguments.length; i++) {
      arg = arguments[i];

      if (arg instanceof Date) {
        seed += arg.getTime();
        seed += arg.getTimezoneOffset();
      } else if ((typeof Event != 'undefined') && (arg instanceof Event)) {
        for (prop in arg) {
          seed += arg[prop];
        }
      } else {
        seed += arg;
      }
    }

    for (i = seed.length - 1; i >= 0; i--) {
      hash = (hash + seed.charCodeAt(i)) * 69069 >>> 0;
      switch (i % 4) {
        case 0:
          x ^= hash;
          break;
        case 1:
          y ^= hash;
          break;
        case 2:
          z ^= hash;
          break;
        case 3:
          w ^= hash;
          break;
      }
    }

    if (y == 0) {
      y = 1;
    }

    c ^= z >>> 31;
    z &= 0x7fffffff;
    if (!(z % 7559)) {
      z++;
    }

    w &= 0x7fffffff;
      if (!(w % 7559)) {
      w++;
    }
  }

  this.getState = function() {
    return {
      x: x,
      y: y,
      z: z,
      w: w,
      c: c,
      hash: hash
    }
  }

  this.setState = function(state) {
    x = state.x;
    y = state.y;
    z = state.z,
    w = state.w;
    c = state.c;
    hash = state.hash;
  }

  this.reSeed.apply(this, arguments);

}

WARNING : I know next to nothing about cross-browser issues, I don't
usually write for the World Wide Web. E.g., in reSeed, I assume that if
Event is defined and something is an instanceof Event, that something
is indeed a DOM event whose properties may be implicitly converted
to Strings and concatenated in a for ... in statement, and that the
resulting string will indeed contain at least a timestamp with a
theoretical millisecond resolution, the mouse coordinates in the case
of mouse events, the key involved in the case of key events, etc. For
all I know, these could be wild assumptions in some browsers.

Feedback on such and other issues would be much appreciated.

--
Johannes


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google