www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Very strange? Code generation bug?

reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
with this program:

<code>
import std.stdio;
import std.random;

float random1()
{
  float f = rand()%101;
  return (f-50)/50;
}

float random2()
{
  return (rand()%101-50)/50;
}

void main()
{
  for(int i=0;i<10;i++)
  {
    writef(random1(), " ");
  }

  writefln("\n");

  for(int i=0;i<10;i++)
  {
    writef(random2(), " ");
  }
}
</code>

i get output something like (Windows XP, DMD 0.153):

0.4 0.28 -0.46 0.2 0.48 0.7 -0.7 -0.18 -0.56 0.2

0 8.58993e+07 8.58993e+07 0 8.58993e+07 8.58993e+07 0 0 0 0


The problem is both functions random1 and random2 should be returning a
number between -1 and 1 and they are doing the same calculation, but
there is something wrong with random2.

Can someone please confirm this?
Apr 11 2006
next sibling parent Tom S <h3r3tic -remove-.mat.uni.torun.pl> writes:
Ivan Senji wrote:
 float random1()
 {
   float f = rand()%101;
   return (f-50)/50;
 }

This is what happens: 1. rand() returns a random uint. It gets warped in the range 0 .. 100 2. the uint from 0 .. 100 is stored into a float 3. you subtract 50 and divide by 50. everything is fine.
 float random2()
 {
   return (rand()%101-50)/50;
 }

This is what happens: 1. rand() returns a random uint. It gets warped in the range 0-100 2. you subtract 50 from the uint in range 0 .. 100, thus possibly wrapping it around its 0xffffffff boundary, thus getting an uint in range (0xffffffff - 50) .. 50 3. you divide the uint by 50, thus yielding a very big number if it were from the range (0xffffffff - 50) .. 0xffffffff or 1 if it were 50 or 0 if it were from the range 0 .. 49 Hope this helps :) -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y ------END GEEK CODE BLOCK------ Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Apr 11 2006
prev sibling next sibling parent BCS <BCS_member pathlink.com> writes:
Well if you pull the rand out you get a different wrong range (~[-3,1])

float random3()
{
	int r = rand();
	return cast(float)((r%101) - 50)/50.0;
}




Ivan Senji wrote:
 with this program:
 
 <code>
 import std.stdio;
 import std.random;
 
 float random1()
 {
   float f = rand()%101;
   return (f-50)/50;
 }
 
 float random2()
 {
   return (rand()%101-50)/50;
 }
 
 void main()
 {
   for(int i=0;i<10;i++)
   {
     writef(random1(), " ");
   }
 
   writefln("\n");
 
   for(int i=0;i<10;i++)
   {
     writef(random2(), " ");
   }
 }
 </code>
 
 i get output something like (Windows XP, DMD 0.153):
 
 0.4 0.28 -0.46 0.2 0.48 0.7 -0.7 -0.18 -0.56 0.2
 
 0 8.58993e+07 8.58993e+07 0 8.58993e+07 8.58993e+07 0 0 0 0
 
 
 The problem is both functions random1 and random2 should be returning a
 number between -1 and 1 and they are doing the same calculation, but
 there is something wrong with random2.
 
 Can someone please confirm this?

Apr 11 2006
prev sibling next sibling parent Dave <Dave_member pathlink.com> writes:
Ivan Senji wrote:
 with this program:
 
 <code>
 import std.stdio;
 import std.random;
 
 float random1()
 {
   float f = rand()%101;
   return (f-50)/50;
 }
 
 float random2()
 {
   return (rand()%101-50)/50;
 }
 
 void main()
 {
   for(int i=0;i<10;i++)
   {
     writef(random1(), " ");
   }
 
   writefln("\n");
 
   for(int i=0;i<10;i++)
   {
     writef(random2(), " ");
   }
 }
 </code>
 
 i get output something like (Windows XP, DMD 0.153):
 
 0.4 0.28 -0.46 0.2 0.48 0.7 -0.7 -0.18 -0.56 0.2
 
 0 8.58993e+07 8.58993e+07 0 8.58993e+07 8.58993e+07 0 0 0 0
 
 
 The problem is both functions random1 and random2 should be returning a
 number between -1 and 1 and they are doing the same calculation, but
 there is something wrong with random2.
 
 Can someone please confirm this?

Give this a shot: ;--- import std.stdio; import std.random; float random1() { float f = rand()%101; return (f-50)/50; } float random2() { //return (rand()%101-50)/50; return (cast(float)(rand()%101)-50)/50; } void main() { rand_seed(10,10); for(int i=0;i<10;i++) { writef(random1(), " "); } writefln("\n"); rand_seed(10,10); for(int i=0;i<10;i++) { writef(random2(), " "); } writefln("\n"); }
Apr 11 2006
prev sibling parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Thank you guys for replying and especially Tom S for explaining this, I
get it now. It wasn't D it was me.

What works great is what Dave suggested
return (cast(float)(rand()%101)-50)/50;
but this shorter version works also
return (rand()%101)-50.)/50;

What I have learned is to be more careful with unsigned numbers and - :)
Apr 11 2006