Steel Rat
Steel Rat

Reputation: 91

Setting a variable back to zero

I'm teaching myself Java using one of the ebooks on Amazon. I was doing one of the lessons which does a "benchmark" of the computer. It does this by looping for a minute and calculating the results.

It basically doesn't show you anything for a minute until it's done. So my was making a small modification to show a dot as a progress bar of sorts every few seconds. Normally this is a trivial thing, but something's not right, and I don't know what.

What happens is miniIndex will reach the threshold I specified, and print the value of miniIndex and a period. Its then supposed to set miniIndex to zero so that counter can restart. But it doesn't reset, and never increments again. It's very odd behavior.

Here is the code in its entirety:

class Benchmark {
    public static void main(String[] arguments) {

        long startTime = System.currentTimeMillis();
        long endTime = startTime + 60000;
        long index = 0;

        // My inner index
        int miniIndex = 0;
        //
        while (true) {
            double x = Math.sqrt(index);
            long now = System.currentTimeMillis();
            if (now > endTime){
                break;
            }
            index++;
            // my modification
            miniIndex++;
            if (miniIndex >= 5000) {
                System.out.print(miniIndex + ".");
                miniIndex = 0;
            }
            // end of my modification
        }
        System.out.println(index + " loops in one minute.");
    }
}

Upvotes: 8

Views: 1448

Answers (5)

ai006
ai006

Reputation: 27

To see why it didn't work, you need to print the variable "now" while looping. You will notice that "now" stays the same for a certain amount while in the loop and eventually it will increment by one. So when you have one thousand of those increments it equates to a period of 1 sec. What the variable "miniIndex" is doing is counting up to 5000 loops and then resets, nowadays computers can perform thousands and thousands of loops in a second. Which is why it seemed like it wasn't resetting.

You can change the wait variable in the code to show different dot progress like you wanted.

    class Main {
      public static void main(String[] args) {


            long startTime = System.currentTimeMillis();
            long endTime = startTime + 60000;
            long index = 0;

            long wait  = 5000; //secs  5000 == 5sec

            long secondsPassed = startTime + wait; 

            System.out.print("counting");
            while (true) {
                double x = Math.sqrt(index);
                long now = System.currentTimeMillis();
                if (now > endTime){
                    break;
                }
                index++;

                if (now >= secondsPassed) {
                    System.out.print(".");
                    secondsPassed = secondsPassed + wait;
                }


            }
            System.out.println("");
            System.out.println(index + " loops in one minute.");
      }
    }

Upvotes: 0

Nexevis
Nexevis

Reputation: 4667

I think you misunderstand what your miniIndex++ operation is doing, as it is not counting milliseconds but instead is counting the number of loop iterations which are not equal to each other. I have modified your code to execute the if statement inside every 5 seconds, according to what you wanted to happen:

public static void main(String[] arguments) {

    long startTime = System.currentTimeMillis();
    long miniTime = startTime; //Declare miniTime equal to startTime
    long endTime = startTime + 60000;
    long index = 0;

    while (true) {
        double x = Math.sqrt(index);
        long now = System.currentTimeMillis();
        if (now > endTime){
            break;
        }
        index++;

        // my modification    
        //Current time minus last time the if executed and check if 5 seconds passed
        if ((now - miniTime) >= 5000) { 
            miniTime = System.currentTimeMillis();
            System.out.println("5 seconds have passed.");

            //if you want to print the actual time elapsed every 5 seconds use this print
            //System.out.println((now - startTime)/1000 + " seconds have passed.");
        }
        // end of my modification
    }
    System.out.println(index + " loops in one minute.");
}

Notice how I now compare current time of now and subtract the miniTime to check to see if it is higher than or equal 5000 milliseconds. To use time you must relate it to time somehow, in this case System.currentTimeMillis() and the results. Numbers themselves such as counting the loop will never be time consistent.

A loop may execute millions of times, but only take 3 seconds.

Example Output:

5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
16319642816 loops in one minute.

Note: 5 seconds have passed. prints 11 times because at the 60 second mark the loop is broken so the final pass is not printed. (And 11 * 5 is 55 for the first 55 seconds).

Upvotes: 9

Avi
Avi

Reputation: 2641

You're probably overwhelming your output or something, such that it doesn't print anything at all. Your loop waits until 60000 milliseconds (1 minute). When I ran it, here was the end part of my output. Since your loop iterates very very fast (as fast as the computer can print, because that is the bottleneck here), NOT one iteration per second/millisecond, your counter miniIndex goes up many many times per second. However, your code does work - it just doesn't do what you think it does.

If you try something like the following, you may get a slightly more precise output:

class Benchmark {
    public static void main(String[] arguments) {

        long startTime = System.currentTimeMillis();
        long endTime = startTime + 60000;
        long index = 0;

        // My inner index
        int miniIndex = 0;
        //
        while (true) {
            double x = Math.sqrt(index);
            long now = System.currentTimeMillis();
            if (now > endTime){
                break;
            }
            index++;
            // my modification
            miniIndex++;
            if (miniIndex >= 5000) {
                System.out.print(miniIndex + ".");
                miniIndex = 0;
            }
            // end of my modification
            try {
                Thread.sleep(1);
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
        System.out.println(index + " loops in one minute.");
    }
}

Output:

..........50976 loops in one minute.

Notice that you may not get 60,000 loops a minute, as Thread.sleep(1) can sleep for slightly over 1 millisecond.

Upvotes: 1

Blind Kai
Blind Kai

Reputation: 524

If you still want to use it in that type of output you can make it easier using StringBuilder. It's coded like that:

StringBuilder stringBuilder = new StringBuilder();

and incide the loop like that:

if (miniIndex >= 5000) {
    stringBuilder.append(miniIndex).append(".");
    miniIndex = 0;
}

if (stringBuilder.length() >= 200) {
    System.out.println(stringBuilder);
    stringBuilder.setLength(0);
}

enter image description here

Upvotes: 3

Joseph Larson
Joseph Larson

Reputation: 9058

Your code is working fine; it's your expectations that are flawed.

Your code prints a dot every 5,000 iterations. Which is going to basically spew values. Remember, your CPU is running at something > 2 billion operations a second. You can probably do a few million of those loops per second. Call it a million loops per second, divided by 5000 is 200 dots per second, more or less, anyway.

Upvotes: 5

Related Questions