digitalmars.D - strange math
- Matt Watkins (50/50) Nov 23 2005 I am probably doing something dumb here, but I can't figure it out, so I...
- Oskar Linde (36/62) Nov 23 2005 [snip]
I am probably doing something dumb here, but I can't figure it out, so I am wondering if someone here can help. I am trying to generate a random number between 900 million and 1.1 billion, and store it in a float. Here are the two code segments in question: float div1; //Code segment 1 for(int x = 0; x < 10; x++) { div1 = 1000000000.0f + cast(float)((rand() % 100000000) * ((rand() % 2) * 2 - 1)); writef("%f\n", div1); } //Code segment 2 for(int x = 0; x < 10; x++) { int addval = (rand() % 100000000) * ((rand() % 2) * 2 - 1); div1 = 1000000000.0f + cast(float)(addval); writef("%f\n", div1); } These two segments to me look like they should do the same thing. The only difference between them is that the second segment uses a variable addval to do (rand() % 100000000) * ((rand() % 2) * 2 - 1), where the first one just has the code stuck right in the one line. Here is the output: Code segment 1 1083211520.000000 5233628160.000000 5259153408.000000 1010581632.000000 5244919808.000000 1038838528.000000 1060295488.000000 5250748928.000000 5242580992.000000 1017323776.000000 Code segment 2 987565312.000000 901736640.000000 1040207936.000000 1039182272.000000 978791104.000000 1031670656.000000 1070735040.000000 997212864.000000 1054348672.000000 1069398592.000000 As you can see, the second segment behaves as expected, but the first segment generates random numbers around 1 billion or around 5 billion. Can someone please tell me why the first segment behaves the way it does? Thanks. Also, I think I have the lastest version of the dmd compiler, since I updated no more than 2 weeks ago.
Nov 23 2005
Hi, In article <dm2ar6$1h0f$1 digitaldaemon.com>, Matt Watkins says...I am probably doing something dumb here, but I can't figure it out, so I am wondering if someone here can help. I am trying to generate a random number between 900 million and 1.1 billion, and store it in a float. Here are the two code segments in question: float div1; //Code segment 1 for(int x = 0; x < 10; x++) { div1 = 1000000000.0f + cast(float)((rand() % 100000000) * ((rand() % 2) * 2 - 1)); writef("%f\n", div1); } //Code segment 2 for(int x = 0; x < 10; x++) { int addval = (rand() % 100000000) * ((rand() % 2) * 2 - 1); div1 = 1000000000.0f + cast(float)(addval); writef("%f\n", div1); } These two segments to me look like they should do the same thing. The only difference between them is that the second segment uses a variable addval to do (rand() % 100000000) * ((rand() % 2) * 2 - 1), where the first one just has the code stuck right in the one line. Here is the output:[snip]As you can see, the second segment behaves as expected, but the first segment generates random numbers around 1 billion or around 5 billion. Can someone please tell me why the first segment behaves the way it does? Thanks.Welcome to the wonderful world of integral promotion. :) I've been bitten by exactly this before... (see http://www.digitalmars.com/d/archives/digitalmars/D/28116.html) Here is a breakdown of why this happens: (I hope it is possible to follow) rand() returns uint uint % int gets promoted to uint uint * int gets promoted to uint uint - int gets promoted to uint ((rand() % 2) * 2 - 1) therefore gets promoted to uint... This give two possible numbers: 1u or 4294967295u (rand() % 100000000) also gets promoted to uint two uints get multiplied giving a new uint (will overflow in 50% of the cases) Assume (rand() % 100000000) evaluates to 99999999u... the wounderful nature of 2-compliment math gives: cast(int) 4294967295u * 99999999u == -99999999 Therefore, everything works in the second case. in the first case, you have instead: cast(float) 4294967295u * 99999999u == 4.19497e+09 (approximately) And everything blows up. The cleanest fix to your code may be: #float div1; #for(int x = 0; x < 10; x++) 2) * 2 - 1)); Note: You will get exactly the same results in C. (Not that I've tested...) D has the same integral promotion rules as C has. Regards Oskar
Nov 23 2005