1

I'm currently doing an assignment for school, and I need to create a program that uses Math.random() to get a random value, and depending on the value, output "Heads" or "Tails". It needs to do this 10 times. Then, it needs to find the percentage of times that the program output heads, and how many it output tails. However, it isn't working correctly. It always outputs that heads/tails were 0% of the tosses. Can someone please explain why?

public class HeadsTails
{
    public static void main(String[] args)
    {
        int v;
        double i;

        int heads = 0, tails = 0;

        double headsPercent, tailsPercent;

        for(v = 1; v <= 10; ++v)
        {
            i = Math.random();
            if(i <= 0.5)
            {
                System.out.println("Heads");
                heads = heads + 1;
            }
            else if(i > 0.5)
            {
                System.out.println("Tails");
                tails = tails + 1;
            }
        }
        headsPercent = (heads / 10) * 100;
        tailsPercent = (tails / 10) * 100;
        System.out.println("Heads were " + headsPercent + "% of the tosses.");
        System.out.println("Tails were " + tailsPercent + "% of the tosses.");
    }
}

I am also quite open to any improvements that can be made, besides those that just make the program function properly.

Xerphi
  • 11
  • 4
  • you are doing an intiger division, the result will be `0` or `1`, since the division can´t have any floating points. – SomeJavaGuy Apr 27 '16 at 10:55
  • @Tom Oh, this is indeed a duplicate of that question. My bad, still new to this whole setup. – Xerphi Apr 27 '16 at 11:34

1 Answers1

1

The problem is integer math. heads and tails are both int, so:

heads / 10

...yields an int result, which will almost always be 0 in your case because in int-land, 1 / 10, 2 / 10, through 9 / 10 are all 0. The only time you'd get anything else would be if all the rolls were heads or all were tails, where 10 / 10 is 1.

Cast to double before doing the math:

headsPercent = ((double)heads / 10) * 100;
tailsPercent = ((double)tails / 10) * 100;

Doing that fixes the problem.


Side note 1: You can add to a variable using +=, e.g.:

heads += x;

And of course, when what you're adding is 1, you can just use the increment operators, either prefix:

++heads;

or postfix

heads++;

(In terms of updating heads and tails, it doesn't matter which.)

Side note 2: You don't need else if (i > 0.5). If you think about the logic, you have if (i <= 0.5) ... else ... That means that i will definitely be > 0.5 once you get to the else, no need for the if (i > 0.5) part.

And if you do that, you don't even need i anymore:

for(v = 1; v <= 10; ++v)
{
    if(Math.random() <= 0.5)
    {
        System.out.println("Heads");
        ++heads;
    }
    else
    {
        System.out.println("Tails");
        ++tails;
    }
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Or - if casting is really as bad as they say it is - you can use `10.0` and `100.0` or `10f` and `100f`. – OldCurmudgeon Apr 27 '16 at 10:58
  • @OldCurmudgeon: Good point. This is one of the relatively few reasonable use cases for casting, but yes, you can indeed use literal double values instead. (But I really wouldn't use literal floats.) That trades explicit casting for *implicit* numeric promotion on the `int`s (and is more subtle), so for me the cast is the right thing. But that would work too. – T.J. Crowder Apr 27 '16 at 11:10
  • 1
    Wow, that was quite in-depth. I can't believe I forgot to fix heads and tails into double, and that that was the only thing holding me back from getting this done. Also, I do/did know of +=, prefix, and postfix, but as I'm not comfortable with them, I didn't use them. I will now, though. Thanks a ton, this has been gnawing at my sanity for the past several hours. – Xerphi Apr 27 '16 at 11:33