0

Here is my run for method for thread

public void run() {
    float timeElapsed =0;
    while(running){
        time += timeElapsed; // recording time.
        if(timeElapsed != 0 )Log.d(id, "pressed time " + time + " "+ timeElapsed);
/**fromhere :: just how I get fps ratio.
        oneSec += timeElapsed;
        fpsCompound++;
        if(oneSec > 1){
            fpsCompound = 0;
            oneSec = 0;
        }
**/endhere 
        timeBefore = System.nanoTime();
        loopCall(timeElapsed);
        timeElapsed =(System.nanoTime()-timeBefore)/1000000000;
//sometimes my timeElapsed is 0, my guess is because the loopCall does nothing in some cases
        while(timeElapsed < .005){
            timeElapsed =(System.nanoTime()-timeBefore)/1000000000;
        }
    }
}

I want to get rid of that while loop that delays the loop if timeElapsed is less than .005.

However if I skip that delay portion, I sometimes get my timeElapsed as 0 even though there has to be a tiny portion of seconds passed.

Accumulated result of these zero elapsed time results in unexpected time error. So I delay my thread if each loop is too fast to record the time.

This unnecessary delay seems pretty stupid. There must be a correct way to calculate the time.

EDIT:

It seems that dividing timeElapsed by 1000000000 returns value that's too small for my float to contain. Is there a way to contain such a small number?

BlueBug
  • 369
  • 4
  • 17
  • 3
    This sounds like a classic [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). What's the *real* problem you're trying to solve with your elapsed time loop? There may be a much better method available. – Duncan Jones May 14 '13 at 09:08
  • 1
    You are using integer division. It will be 0. – jlordo May 14 '13 at 09:10
  • Thank you Duncan Jones. I just realized what's the "problem" let me edit the question . – BlueBug May 14 '13 at 09:11
  • @jlordo I don't get 0. – BlueBug May 14 '13 at 09:13
  • @DuncanJones It seems that dividing timeElapsed by 1000000000 returns value that's too small for my float to contain. Is there a way to contain such a small number? – BlueBug May 14 '13 at 09:13
  • @jlordo not quite `System.out.println((12.3-10)/3);` – Stephan May 14 '13 at 09:13
  • @BlueBug use `Double` you can read more here: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html – Stephan May 14 '13 at 09:14
  • @BlueBug Read my link carefully. It feels to me like you've already found a solution to a problem and you're asking for help with your implementation. Perhaps if you explained *why* you are trying to write this code, we can suggest an alternative route. – Duncan Jones May 14 '13 at 09:14
  • @Stephan: there are no floats or doubles in OPs code. It's `(long-long)/int` – jlordo May 14 '13 at 09:15
  • @jlordo `float timeElapsed =0;` if it was like you said you are right he should get 0 – Stephan May 14 '13 at 09:15
  • @Stephan: run this code: `float f = (12.3-10)/3; System.out.println(f);` and see what happens... – jlordo May 14 '13 at 09:16
  • in fact, timeBefore is float, so (long-float), my bad i should had specified it. – BlueBug May 14 '13 at 09:18
  • @BlueBug: I assumed `timeBefore` was a `long`, because you assigned a `long` to it. Why do you use `float` instead of `double`? Yep, you should have specified it... – jlordo May 14 '13 at 09:19
  • @jlordo indeed if you cast if to `float` it will give you `0.76666665 ` but if you put `System.out.println((12.3-10)/3);` the conversion is done automatically – Stephan May 14 '13 at 09:20
  • 1
    @DuncanJones This is a part of game loop that does update. I want to hide an image for x amount of time, but since time passed is too small, I am better off using other variables than float for my timeElapsed. Should I just use other type such as long for this kind of time sensitive code? or is it "alright" to delay if time passed is too little to care. – BlueBug May 14 '13 at 09:21
  • @Stephan I did not know how to call two names at a time, so I called u here. same comment that I just did to #DuncanJones. – BlueBug May 14 '13 at 09:22
  • @jlordo I see your code, indeed you are right, but I somehow am getting less than 1. – BlueBug May 14 '13 at 09:24
  • 1
    @Stephan: Our conversation is starting to become off-topic ;) My example was bad, I assumed OP hat `float = (long-long)/int`. My example should have been: `float f = (12L-10L)/3; System.out.println(f);` – jlordo May 14 '13 at 09:24
  • @BlueBug: Yes, all my comments were based on the assumption that `timeBefore` was a `long` variable... – jlordo May 14 '13 at 09:25
  • @jlordo you were right :) the case is `(long-long)/int` so you should post a answer – Stephan May 14 '13 at 09:38
  • @Stephan: no, OP said in the comments that `timeBefore` is a `float`, which makes it `float=(long-float)/int`, which will work fine. – jlordo May 14 '13 at 09:41
  • @jlordo sorry i wasn't clear , if the case was `float=(long-long)/int` then the result could be 0 – Stephan May 14 '13 at 09:45

1 Answers1

2

I think you should keep nanoseconds as long and not convert it into float seconds.

then you'll have code like this: timeElapsed is defined as long:

            long timeElapsed = 0;

End of your loop will look like this:

            timeBefore = System.nanoTime();
            loopCall(timeElapsed);
            timeElapsed =(System.nanoTime()-timeBefore);        
            while(timeElapsed < 5000000){
                timeElapsed = (System.nanoTime()-timeBefore);
            }

I hope that's what you're looking for.


Also I'd recommend to do waiting with Thread.sleep(long, int); You'll lose some precision (it sleeps for milliseconds) but will save some CPU time

         /*while(timeElapsed < 5000000){
              timeElapsed = (System.nanoTime()-timeBefore);
           }*/


           long leftToSleep = 5000000 - timeElapsed;
           if(leftToSleep > 0) {
              //dont forget to surround it with try catch
              Thread.sleep(leftToSleep / 1000000, (int) leftToSleep % 1000000);
           }
Bitman
  • 1,996
  • 1
  • 15
  • 18