I''m a noob Ruby user, but IronRuby behaves different from other Ruby implementations that I''ve tried, in IronRuby (rev 121) this code: 100.times {p rand(100)} Often returns the same value for (almost) all iterations, like this: 2 2 2 2 2 2 2 2 ...and so on... Works as designed? Need to seed it or something? /Johan -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/ironruby-core/attachments/20080706/4f69f160/attachment-0001.html>
By default, the parameterless constructor of the System.Random class (which is what we''re using) uses the system time as the initial seed. Every time you ask for a random number, we create a new Random object, and in a tight loop like yours, they''ll probably all get the same seed. We should probably create a single Random object the first time that one is requested and store it in the RubyContext. From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Johan Danforth Sent: Sunday, July 06, 2008 7:28 AM To: ironruby-core at rubyforge.org Subject: [Ironruby-core] rand() needs a seed? I''m a noob Ruby user, but IronRuby behaves different from other Ruby implementations that I''ve tried, in IronRuby (rev 121) this code: 100.times {p rand(100)} Often returns the same value for (almost) all iterations, like this: 2 2 2 2 2 2 2 2 ...and so on... Works as designed? Need to seed it or something? /Johan -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/ironruby-core/attachments/20080706/a79e1752/attachment.html>
Like this? private static readonly Random rndGen = new Random(); [RubyMethod("rand", RubyMethodAttributes.PrivateInstance)] [RubyMethod("rand", RubyMethodAttributes.PublicSingleton)] public static double Rand(CodeContext/*!*/ context, object self) { lock(rndGen) return rndGen.NextDouble(); } [RubyMethod("rand", RubyMethodAttributes.PrivateInstance)] [RubyMethod("rand", RubyMethodAttributes.PublicSingleton)] public static object Rand(CodeContext/*!*/ context, object self, int limit) { if (limit == 0) return Rand(context, self); lock (rndGen) return RuntimeHelpers.Int32ToObject((int)(rndGen.NextDouble() * (limit - 1))); } [RubyMethod("rand", RubyMethodAttributes.PrivateInstance)] [RubyMethod("rand", RubyMethodAttributes.PublicSingleton)] public static object Rand(CodeContext/*!*/ context, object self, double limit) { if (limit < 1) return Rand(context, self); lock (rndGen) return RuntimeHelpers.Int32ToObject((int)(rndGen.NextDouble() * (limit - 1))); } I put a lock() on each call as well, because I believe the Next-methods aren''t thread safe. Works for me. /Johan From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Curt Hagenlocher Sent: den 6 juli 2008 17:16 To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] rand() needs a seed? By default, the parameterless constructor of the System.Random class (which is what we''re using) uses the system time as the initial seed. Every time you ask for a random number, we create a new Random object, and in a tight loop like yours, they''ll probably all get the same seed. We should probably create a single Random object the first time that one is requested and store it in the RubyContext. From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Johan Danforth Sent: Sunday, July 06, 2008 7:28 AM To: ironruby-core at rubyforge.org Subject: [Ironruby-core] rand() needs a seed? I''m a noob Ruby user, but IronRuby behaves different from other Ruby implementations that I''ve tried, in IronRuby (rev 121) this code: 100.times {p rand(100)} Often returns the same value for (almost) all iterations, like this: 2 2 2 2 2 2 2 2 ...and so on... Works as designed? Need to seed it or something? /Johan -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/ironruby-core/attachments/20080706/9ac4a67e/attachment.html>
Something like that, yes, but making it a static member of KernelOps means that we have to pay the construction cost during startup. For a function as infrequently used as "rand", it might be better to initialize it more lazily. From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Johan Danforth Sent: Sunday, July 06, 2008 9:51 AM To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] rand() needs a seed? Like this? private static readonly Random rndGen = new Random(); [RubyMethod("rand", RubyMethodAttributes.PrivateInstance)] [RubyMethod("rand", RubyMethodAttributes.PublicSingleton)] public static double Rand(CodeContext/*!*/ context, object self) { lock(rndGen) return rndGen.NextDouble(); } [RubyMethod("rand", RubyMethodAttributes.PrivateInstance)] [RubyMethod("rand", RubyMethodAttributes.PublicSingleton)] public static object Rand(CodeContext/*!*/ context, object self, int limit) { if (limit == 0) return Rand(context, self); lock (rndGen) return RuntimeHelpers.Int32ToObject((int)(rndGen.NextDouble() * (limit - 1))); } [RubyMethod("rand", RubyMethodAttributes.PrivateInstance)] [RubyMethod("rand", RubyMethodAttributes.PublicSingleton)] public static object Rand(CodeContext/*!*/ context, object self, double limit) { if (limit < 1) return Rand(context, self); lock (rndGen) return RuntimeHelpers.Int32ToObject((int)(rndGen.NextDouble() * (limit - 1))); } I put a lock() on each call as well, because I believe the Next-methods aren''t thread safe. Works for me. /Johan From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Curt Hagenlocher Sent: den 6 juli 2008 17:16 To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] rand() needs a seed? By default, the parameterless constructor of the System.Random class (which is what we''re using) uses the system time as the initial seed. Every time you ask for a random number, we create a new Random object, and in a tight loop like yours, they''ll probably all get the same seed. We should probably create a single Random object the first time that one is requested and store it in the RubyContext. From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Johan Danforth Sent: Sunday, July 06, 2008 7:28 AM To: ironruby-core at rubyforge.org Subject: [Ironruby-core] rand() needs a seed? I''m a noob Ruby user, but IronRuby behaves different from other Ruby implementations that I''ve tried, in IronRuby (rev 121) this code: 100.times {p rand(100)} Often returns the same value for (almost) all iterations, like this: 2 2 2 2 2 2 2 2 ...and so on... Works as designed? Need to seed it or something? /Johan -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/ironruby-core/attachments/20080706/7b20dc56/attachment-0001.html>
Note there is also srand() method that seeds the generator. The generator therefore needs to be associated with RubyExecutionContext. Tomas From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Curt Hagenlocher Sent: Sunday, July 06, 2008 11:49 AM To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] rand() needs a seed? Something like that, yes, but making it a static member of KernelOps means that we have to pay the construction cost during startup. For a function as infrequently used as "rand", it might be better to initialize it more lazily. From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Johan Danforth Sent: Sunday, July 06, 2008 9:51 AM To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] rand() needs a seed? Like this? private static readonly Random rndGen = new Random(); [RubyMethod("rand", RubyMethodAttributes.PrivateInstance)] [RubyMethod("rand", RubyMethodAttributes.PublicSingleton)] public static double Rand(CodeContext/*!*/ context, object self) { lock(rndGen) return rndGen.NextDouble(); } [RubyMethod("rand", RubyMethodAttributes.PrivateInstance)] [RubyMethod("rand", RubyMethodAttributes.PublicSingleton)] public static object Rand(CodeContext/*!*/ context, object self, int limit) { if (limit == 0) return Rand(context, self); lock (rndGen) return RuntimeHelpers.Int32ToObject((int)(rndGen.NextDouble() * (limit - 1))); } [RubyMethod("rand", RubyMethodAttributes.PrivateInstance)] [RubyMethod("rand", RubyMethodAttributes.PublicSingleton)] public static object Rand(CodeContext/*!*/ context, object self, double limit) { if (limit < 1) return Rand(context, self); lock (rndGen) return RuntimeHelpers.Int32ToObject((int)(rndGen.NextDouble() * (limit - 1))); } I put a lock() on each call as well, because I believe the Next-methods aren''t thread safe. Works for me. /Johan From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Curt Hagenlocher Sent: den 6 juli 2008 17:16 To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] rand() needs a seed? By default, the parameterless constructor of the System.Random class (which is what we''re using) uses the system time as the initial seed. Every time you ask for a random number, we create a new Random object, and in a tight loop like yours, they''ll probably all get the same seed. We should probably create a single Random object the first time that one is requested and store it in the RubyContext. From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Johan Danforth Sent: Sunday, July 06, 2008 7:28 AM To: ironruby-core at rubyforge.org Subject: [Ironruby-core] rand() needs a seed? I''m a noob Ruby user, but IronRuby behaves different from other Ruby implementations that I''ve tried, in IronRuby (rev 121) this code: 100.times {p rand(100)} Often returns the same value for (almost) all iterations, like this: 2 2 2 2 2 2 2 2 ...and so on... Works as designed? Need to seed it or something? /Johan -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/ironruby-core/attachments/20080706/086403dd/attachment.html>