www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Strange behaviour of var

reply Fabian <talk2fab online.de> writes:
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
next sibling parent reply Tobias Brandt <tob.brandt googlemail.com> writes:
'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=
the
 Monte 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 =
try
 to calculate PI. But why? Please help me.

 Nice wishes
 Fabian
Nov 10 2011
parent Fabian <talk2fab online.de> writes:
Thank you - now it works :)
Nov 10 2011
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
parent reply Fabian <talk2fab online.de> writes:
oh ... I see. Thank you ;)
Nov 10 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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