rand(-10..10)

Discussion in 'Ruby' started by Schüle Daniel, Jul 27, 2006.

  1. Hi all,

    wouldn't it make sense to allow

    rand -10..10

    be aquivalent to

    -10 + rand(20)

    the first is by far more obvious.
    Of course rand -10...10 should work too.
    What do you think?


    --
    Daniel
    Schüle Daniel, Jul 27, 2006
    #1
    1. Advertising

  2. one solution could be

    irb(main):210:0* class Range
    irb(main):211:1> def rand
    irb(main):212:2> return self.begin + Kernel.rand(self.end-self.begin)
    irb(main):213:2> end
    irb(main):214:1> end
    => nil
    irb(main):215:0> (-10..10).rand
    => 2
    irb(main):216:0> (-10..10).rand
    => 6
    irb(main):217:0> (-10..10).rand
    => 4
    irb(main):218:0> (-10..10).rand
    => -1

    it's a matter of style to write

    rand(-10..10) or (-10..10).rand

    but since 10.sin doesn't work, as opposite tosin(10)
    non object oriented rand(-10..10) is also a nice thing to have.
    Schüle Daniel, Jul 27, 2006
    #2
    1. Advertising

  3. I had similar thoughts a while back. I decided that extending Kernel =20
    and mimicing the behavior of rand was the way to go. My code follows:

    Regards, Morton

    ------ code starts
    #!/usr/bin/ruby

    # Extend Kernel with an enhanced uniform random number generator.
    # Has the same behavior as rand for a single argument.
    module Kernel
    URAND_ARG_ERR =3D "Arguments not valid for urand"
    # Return a pseudo-random number in the range 0.0...1.0, 0...m, or =20=

    m..n.
    def urand(m=3D0, n=3Dnil)
    case m
    when Range
    m, n =3D m.begin, m.end
    when Integer
    return rand(m) if n.nil?
    else
    raise ArgumentError, URAND_ARG_ERR
    end
    raise ArgumentError, URAND_ARG_ERR if n < m
    m + rand(n - m + 1)
    end
    end

    # Now for a little testing ...
    def test(times, m=3D0, n=3Dnil)
    r =3D Array.new(times)
    if n.nil? then
    if m =3D=3D 0 then r.collect! {urand}
    else r.collect! {urand(m)}
    end
    else r.collect! {urand(m, n)}
    end
    p r
    end
    test(3) # =3D> [0.0403243284672499, 0.875487065408379, =20
    0.142408860381693]
    test(3, 11, 11) # =3D> [11, 11, 11]
    test(10, 3) # =3D> [0, 1, 2, 0, 1, 0, 1, 2, 0, 0]
    test(10, -1..1) # =3D> [0, 0, 1, -1, -1, 1, -1, 1, -1, 0]
    test(10, 100, 200) # =3D> [126, 148, 183, 140, 188, 175, 115, 157, 136, =20=

    179]
    begin
    test(1, 3, -1)
    rescue ArgumentError =3D> error
    puts error.message
    end # =3D> Arguments not valid for urand

    ------ code ends

    On Jul 26, 2006, at 8:50 PM, Sch=FCle Daniel wrote:

    > one solution could be
    >
    > irb(main):210:0* class Range
    > irb(main):211:1> def rand
    > irb(main):212:2> return self.begin + Kernel.rand(self.end-self.begin)
    > irb(main):213:2> end
    > irb(main):214:1> end
    > =3D> nil
    > irb(main):215:0> (-10..10).rand
    > =3D> 2
    > irb(main):216:0> (-10..10).rand
    > =3D> 6
    > irb(main):217:0> (-10..10).rand
    > =3D> 4
    > irb(main):218:0> (-10..10).rand
    > =3D> -1
    >
    > it's a matter of style to write
    >
    > rand(-10..10) or (-10..10).rand
    >
    > but since 10.sin doesn't work, as opposite tosin(10)
    > non object oriented rand(-10..10) is also a nice thing to have.
    Morton Goldberg, Jul 27, 2006
    #3
  4. Schüle Daniel

    Dr Nic Guest

    > irb(main):215:0> (-10..10).rand
    > => 2
    > irb(main):216:0> (-10..10).rand
    > => 6
    > irb(main):217:0> (-10..10).rand
    > => 4
    > irb(main):218:0> (-10..10).rand
    > => -1


    *Sniff* God I love Ruby.

    --
    Posted via http://www.ruby-forum.com/.
    Dr Nic, Jul 27, 2006
    #4
  5. Schüle Daniel

    Marc Heiler Guest

    "the first is by far more obvious."

    I think it looks ugly. :)

    (-10..10).rand
    looks much nicer IMHO.


    --
    Posted via http://www.ruby-forum.com/.
    Marc Heiler, Jul 27, 2006
    #5
  6. Marc Heiler wrote:
    > "the first is by far more obvious."
    >
    > I think it looks ugly. :)
    >
    > (-10..10).rand
    > looks much nicer IMHO.


    This should work with all enumerables:

    module Enumerable
    def rand
    entries = entries
    entries.at(Kernel.rand(entries.length))
    end
    end

    I can't seem to get around the `entries = entries' part -- I don't want
    to convert the enumerable to an array more than once. Any ideas?


    Cheers,
    Daniel
    Daniel Schierbeck, Jul 27, 2006
    #6
  7. Schüle Daniel

    ChrisH Guest

    Daniel Schierbeck wrote:
    ....
    > This should work with all enumerables:
    >
    > module Enumerable
    > def rand
    > entries = entries
    > entries.at(Kernel.rand(entries.length))
    > end
    > end
    >
    > I can't seem to get around the `entries = entries' part -- I don't want
    > to convert the enumerable to an array more than once. Any ideas?


    Enumerable supports sort_by, so could just use:

    module Enumerable
    def rand
    self.sort_by{Kernel.rand}.last
    end
    end

    Cheers
    Chris
    ChrisH, Jul 27, 2006
    #7
  8. ChrisH wrote:
    > Daniel Schierbeck wrote:
    > ...
    >> This should work with all enumerables:
    >>
    >> module Enumerable
    >> def rand
    >> entries = entries
    >> entries.at(Kernel.rand(entries.length))
    >> end
    >> end
    >>
    >> I can't seem to get around the `entries = entries' part -- I don't want
    >> to convert the enumerable to an array more than once. Any ideas?

    >
    > Enumerable supports sort_by, so could just use:
    >
    > module Enumerable
    > def rand
    > self.sort_by{Kernel.rand}.last
    > end
    > end


    I think sorting the entire enumerable may be slight overkill, although
    it of course is prettier :)


    Daniel
    Daniel Schierbeck, Jul 27, 2006
    #8
  9. Daniel Schierbeck <> writes:

    >>> This should work with all enumerables:
    >>>
    >>> module Enumerable
    >>> def rand
    >>> entries = entries
    >>> entries.at(Kernel.rand(entries.length))
    >>> end
    >>> end
    >>>
    >>> I can't seem to get around the `entries = entries' part -- I don't want
    >>> to convert the enumerable to an array more than once. Any ideas?


    There's also this, which is possibly more memory-efficient (if the
    Enumerable in question chews large amounts of memory when being
    converted to an array, but not with each), but is almost certainly
    much slower, since it calls rand once per element:

    module Enumerable
    def rand
    ret, i = nil, 0
    each {|v| ret = v if 0 == Kernel.rand(i += 1)}
    ret
    end
    end

    Test code for irb:

    h=Hash.new(0); 10000.times {h[%w{a b c d e}.rand] += 1}; h
    Daniel Martin, Jul 27, 2006
    #9
  10. Daniel Martin wrote:
    > module Enumerable
    > def rand
    > ret, i = nil, 0
    > each {|v| ret = v if 0 == Kernel.rand(i += 1)}
    > ret
    > end
    > end
    >
    > Test code for irb:
    >
    > h=Hash.new(0); 10000.times {h[%w{a b c d e}.rand] += 1}; h
    >

    I think you shouldn't name this method rand. It shadows Kernel.rand in
    all classes, that already call rand and include Enumerable. The same is
    true for Range#rand, if people inherit from Range and already call rand.
    Ruby makes those things possible, but it's also very easy to shoot
    yourself or others into the foot, if you aren't careful.

    The Kernel#rand(-5..15) version wouldn't suffer from this problem. It
    would be a good idea to add this to ruby core, because this
    functionality is something, that is needed very often.

    --
    Florian Frank
    Florian Frank, Jul 27, 2006
    #10
  11. [...]

    > The Kernel#rand(-5..15) version wouldn't suffer from this problem. It
    > would be a good idea to add this to ruby core, because this
    > functionality is something, that is needed very often.


    yes, this was exactly my point
    if we already had Kernel#rand with Range object, people wouldn't
    implement their own methods, making scripts shoter and slightly more
    portable (regarding copy&paste other code)

    Regards, Daniel
    Schüle Daniel, Jul 28, 2006
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Niko D. Barli

    rand function in Modelsim 5.7c

    Niko D. Barli, Aug 26, 2004, in forum: VHDL
    Replies:
    9
    Views:
    6,315
    Niko D. Barli
    Sep 6, 2004
  2. daniel kaplan

    rand() question

    daniel kaplan, Sep 15, 2004, in forum: Perl
    Replies:
    4
    Views:
    627
    Ian Sedwell
    Sep 21, 2004
  3. Amelyan

    what is rand?

    Amelyan, Mar 31, 2006, in forum: ASP .Net
    Replies:
    3
    Views:
    543
    Kevin Spencer
    Mar 31, 2006
  4. Orhan Demirel

    usage of rand()

    Orhan Demirel, Jul 21, 2003, in forum: C++
    Replies:
    1
    Views:
    395
    Adam Fineman
    Jul 21, 2003
  5. 7stud --

    rand() v. rand(0.1) ?

    7stud --, Sep 15, 2007, in forum: Ruby
    Replies:
    6
    Views:
    233
    Morton Goldberg
    Sep 16, 2007
Loading...

Share This Page