caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: AUGER <Cedric.Auger@lri.fr>
To: caml-list@inria.fr
Subject: Re: [Caml-list] Random questions
Date: Thu, 03 Dec 2009 12:00:59 +0100	[thread overview]
Message-ID: <op.u4czjxj9l4bj1b@lri4-139> (raw)
In-Reply-To: <91a3da520911180259s585b5ef5j311bd0448ed3c02f@mail.gmail.com>

Le Wed, 18 Nov 2009 11:59:08 +0100, Daniel Bünzli  
<daniel.buenzli@erratique.ch> a écrit:

> I know little about PRGN and unfortunately in a lot of cases the
> functions in the Random module don't provide me the right
> interface. Could anybody tell me if the following functions preserve
> the quality of the underlying PRGN and/or if there's a better way to
> achieve that :
>

(* preliminary function: negate_minus_1 : int -> int : n |-> -n-1 *)
let negate_minus_1 = (lor) (-(max_int/2)-1) (* or inline the constant *)


> 1) Generate an arbitrary int
>
> let rint () = Random.bits () lor ((Random.bits () land 1) lsl 30)
It seems ok to me even if this variant seems slightly more efficient,
since we don't have to bother with making a single bit;
note the use of the xor instead of the or, which keeps the probability of  
one bit to 1/2
(in your example, this probability was kept since one of the bit was  
forced to be 0):

let rint () = (Random.bits () lsl 1) lxor (Random.bits ());;

-or-

let rint () = let r = Random.bits () in
	      if Random.bool () then negate_minus_1 r (* or inline negate_minus_1  
*)
	      else r

note these functions don't rely on the fact ints are on 31 bits
if Random.bool is more efficient than Random.bits, the latter seems the  
best; to be benchmarked...

>
>
> 2) Generate an arbitrary int in [0;max] (bounds included)
>
> let random_uint ?(max = max_int) =
>   if max < 0 then invalid_arg "negative max" else
>   if max = max_int then Random.bits else
>   let bound = max + 1 in
>   fun () -> Random.int bound

Seems correct.
I don't know if use of exception is more efficient or not, it is to try:

let random_uint ?(max = max_int) () =
  try if max = max_int then Random.bits () else Random.int (max + 1)
  with Invalid_argument "Random.int" -> invalid_arg "negative max"

>
>
> 3) Generate an arbitrary int in [-max;max] (bounds included)
>
> let random_int ?(max = max_int) =
>   if max < 0 then invalid_arg "negative max" else
>   if max = max_int then
>     let rec aux () =
>       let v = rint () in if v = min_int then aux () else v in
>       aux
>   else
>     let bound = (2 * max) + 1 in
>     if 0 < bound && bound < max_int then
>       fun () -> -max + Random.int bound
>     else
>       let bound = Int32.add (Int32.mul 2l (Int32.of_int max)) 1l in
>       let min = Int32.of_int (-max) in
>       fun () -> Int32.to_int (Int32.add min (Random.int32 bound))
>
>

I think it is better to use the bool trick;
simpler and doesn't use Int32:

let random_int ?(max = max_int) =
    if max < 0 then invalid_arg "negative max" else
    if max = 0 then 0 else
    if Random.bool ()
    then if max = max_int then Random.bits ()
         else Random.int max
    else negate_minus_1 (Random.int (max - 1)) (* inline? *)

> 5) Generate an arbitrary float in [0;max] (bounds included)
>
> let after_one = 1. +. epsilon_float
> let random_ufloat ?(max = max_float) =
>   if max < 0. then invalid_arg "negative max" else
>   fun () -> (Random.float after_one) *. max
This function is less interesting than Random.float:
only less or as many as values as floats in [0.;1.] can be generated
so you will miss many values only to be able to produce max
(for example, you cannot 1+eps if you try random_ufloat ~max:2. ())

The best would be to have a succ function for floats
>
>
> 6) Generate an arbitrary float in [-max;max] (bounds included)
>
> let after_one = 1. +. epsilon_float
> let random_float ?(max = max_float) =
>   if max < 0. then invalid_arg "negative max" else
>   fun () -> (-1. +. (Random.float after_one) *. 2.) *. max
>
same remark
>
> Thanks for your answers,
>
> Daniel
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs


-- 
Cédric AUGER

Univ Paris-Sud, Laboratoire LRI, UMR 8623, F-91405, Orsay


  reply	other threads:[~2009-12-03 11:01 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-18 10:59 Daniel Bünzli
2009-12-03 11:00 ` AUGER [this message]
2009-12-03 14:48   ` [Caml-list] " Daniel Bünzli
2009-12-03 15:11     ` AUGER
2009-12-03 16:01   ` Damien Doligez
2009-12-03 16:45     ` AUGER

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=op.u4czjxj9l4bj1b@lri4-139 \
    --to=cedric.auger@lri.fr \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).