Thread overview
Strange behaviour of var
Nov 10, 2011
Fabian
Nov 10, 2011
Tobias Brandt
Nov 10, 2011
Fabian
Nov 10, 2011
Ali Çehreli
Nov 10, 2011
Fabian
Nov 10, 2011
Timon Gehr
Nov 10, 2011
Andrej Mitrovic
November 10, 2011
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
November 10, 2011
'hits' and 'n' are both integers and hits < n, therefore hits/n = 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()
> {
>        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
>
November 10, 2011
Thank you - now it works :)
November 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

November 10, 2011
oh ... I see. Thank you ;)
November 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.
November 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. :/