digitalmars.D.learn - Strange behaviour of var
- Fabian (36/36) Nov 10 2011 Hey guys,
- Tobias Brandt (10/46) Nov 10 2011 'hits' and 'n' are both integers and hits < n, therefore hits/n =3D 0
- Fabian (1/1) Nov 10 2011 Thank you - now it works :)
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (14/16) Nov 10 2011 This is not related to your question. I just wanted to point out that it...
- Fabian (1/1) Nov 10 2011 oh ... I see. Thank you ;)
- Timon Gehr (15/16) Nov 10 2011 ++i is unidiomatic, and if the result is unused it means the same thing
- Andrej Mitrovic (13/13) Nov 10 2011 size_t can easily bite you* in the ass:
Hey guys, I've got a problem - I've just written a few lines to approximate PI with the Monte Carlo Method. This is my code: import std.stdio, std.conv, std.string, std.random; void main() { string buf; int n, hits; float x, y, pi; Random rnd; rnd.seed(unpredictableSeed); write("Please enter the number of approximation steps: "); stdin.readln(buf); buf = chomp(buf); if(isNumeric(buf)) { n = parse!int(buf); for(int i = 0; i <= n -1; i++) { x = uniform(0.0f, 1.0f, rnd); y = uniform(0.0f, 1.0f, rnd); if((x*x + y*y) <= 1) { hits++; writeln(hits); //only for debugging } } pi = (hits / n) * 4.f; writeln(pi); } } But the result is always 0 because my var "hits" is set to zero before I try to calculate PI. But why? Please help me. Nice wishes Fabian
Nov 10 2011
'hits' and 'n' are both integers and hits < n, therefore hits/n =3D 0 in integer arithmetic. You need to convert at least one of them to a floating point type, e.g., with 'cast(double)(hits)/n'. On 10 November 2011 21:08, Fabian <talk2fab online.de> wrote:Hey guys, I've got a problem - I've just written a few lines to approximate PI with=theMonte Carlo Method. This is my code: import std.stdio, std.conv, std.string, std.random; void main() { =A0 =A0 =A0 =A0string buf; =A0 =A0 =A0 =A0int n, hits; =A0 =A0 =A0 =A0float x, y, pi; =A0 =A0 =A0 =A0Random rnd; =A0 =A0 =A0 =A0rnd.seed(unpredictableSeed); =A0 =A0 =A0 =A0write("Please enter the number of approximation steps: "); =A0 =A0 =A0 =A0stdin.readln(buf); =A0 =A0 =A0 =A0buf =3D chomp(buf); =A0 =A0 =A0 =A0if(isNumeric(buf)) =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0n =3D parse!int(buf); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0for(int i =3D 0; i <=3D n -1; i++) =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0x =3D uniform(0.0f, 1.0f, =rnd);=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0y =3D uniform(0.0f, 1.0f, =rnd);=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if((x*x + y*y) <=3D 1) =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0hits++; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0writeln(hi=ts); =A0//only for debugging=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pi =3D (hits / n) * 4.f; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0writeln(pi); =A0 =A0 =A0 =A0} } But the result is always 0 because my var "hits" is set to zero before I =tryto calculate PI. But why? Please help me. Nice wishes Fabian
Nov 10 2011
This is not related to your question. I just wanted to point out that it is better to use the normal increment operator in the majority of cases. (I avoid calling it pre-increment, because that name suggests a more complicated semantics than there actually is.) On 11/10/2011 12:08 PM, Fabian wrote:for(int i = 0; i<= n -1; i++)[...]hits++;In both of those lines you want to merely increment the value of a variable. The post-increment operator that you have used has a different meaning: "increment this variable but use its previous value in this expression." Since the previous value is ignored in those expressions, it is better to just increment: ++i and ++hist. Semantically cleaner... :) Ali
Nov 10 2011
On 11/10/2011 10:45 PM, Fabian wrote:oh ... I see. Thank you ;)++i is unidiomatic, and if the result is unused it means the same thing as i++. So, I'd actually go with i++. The only reason why one would use ++i is because it is less efficient for C++ iterators, but D does not have that problem at all. This is really not important though. however, about: for(int i = 0; i <= n -1; i++){} this is the way to go (less gotchas if index is a size_t, which it sometimes should) for(int i = 0; i < n; i++){} But because this exact construct is so common in C and C++, D has an own syntax for it: foreach(i;0..n){} This does exactly the same thing. Always use foreach for trivial iteration.
Nov 10 2011
size_t can easily bite you* in the ass: import std.algorithm; void main() { int[] a; int val = max(0, a.length - 1); assert(val > 0); // NG, woops! } * = me That one is easy to catch, but in a complex expression you might have ints and size_t and everything gets converted to unsigned, and then you end up with some value over int.max which is implicitly assigned to an int. :/
Nov 10 2011