Code archives/Algorithms/Safer Millisecs() Interval

This code has been declared by its author to be Public Domain code.

Download source code

Safer Millisecs() Interval by _PJ_2009
I'm suprised this couldn't be found in the archives already. Sure it's only tiny but there's been a few posts here and there about it, so I thought I'd jot it down.

Basically, there's an upper limit to Blitz' apacity for integers. This value is ((2^31)-1) or 2147483647.
With the Millisecs() function, when the internal timer reaches this amount (After just under 25 days!) then it rolls-over but not to 0, instead it flips to 0-2147483647 and continues counting numerically UPWARDS to 0.
This can cause a lot of issues when certain timing checks rely on the difference between the current count and a previous stored value when the interval overlaps this rollover.
While Not KeyDown(1)
	If (KeyHit(57))
		Print Str(ElapsedSince%(nLast%))
		nLast%=MilliSecs()
	End If
Wend

Function ElapsedSince%(nLast%)
	FlushKeys()
	Local nMilli%=MilliSecs()
	Local nReturn%
	
	If ((Sgn(nLast%))<>(Sgn(nMilli)))
		nReturn=Abs(nLast)+Abs(nMilli)
	Else
		nReturn=nMilli-nLast%
	End If
	Return Abs(nReturn%)
End Function

Comments

Floyd2009
Elapsed time from time1 to time2 is simply the difference time2-time1.

You don't need to do anything else. The possible rollover to negative is irrelevant.


_PJ_2009
I disagree.
In rare infrequent situations with large durations where T2<T1 and (T2>0), that T2-T1 becomes negative: A negative time interval.
Many programs break for this reason.


Floyd2009
A negative elapsed time means the interval is at least 2^31 milliseconds. A signed integer can't hold such a value so there would be no way to return the correct elapsed time.

The situation people usually think will cause trouble is when time1 is a large positive number and a later time2 has rolled over to a negative number. But the difference time2-time1 is still positive.

I am saying that, for example, if you assign any value to t1, then set t2=t1+50 then t2-t1 will be 50. It does not matter if t2 is positive and t1 is negative. Try it.


_PJ_2009
(Posted 7 minutes ago)
A negative elapsed time means the interval is at least 2^31 milliseconds. A signed integer can't hold such a value so there would be no way to return the correct elapsed time.



Exactly, causing potential problems which ARE relevant.

The situation people usually think will cause trouble is when time1 is a large positive number and a later time2 has rolled over to a negative number. But the difference time2-time1 is still positive.

I am saying that, for example, if you assign any value to t1, then set t2=t1+50 then t2-t1 will be 50. It does not matter if t2 is positive and t1 is negative. Try it.


I don't need to try it, nor am I concerned with when T1<T2 since that is always the case in the REAL world. the first check is always PRIOR to the second.

However, as I stated, it is possible to have (T2<T1) and (T2>0) resulting in a negative duration. multiple of rollovers this is possible

Perhaps ' "Accurate" Millisecs()' is a bad chocie of word for the title, but still my code alleviates any breaking situations with interval millisecs checks if not preserving accurate count overall.


TaskMaster2009
As long as you do your math, where you subtract the later number from the earlier number, then the answer will always be correct. That way, T2 is never less than T1.


_PJ_2009
Make the first check. For the sake of argument, let's say it's when Milliseconds returns 1000

T1= 1000

Wait for a 4294966296 milliseconds interval until checking again (T2) At this point, the Milliseconds value would have wrapped to negative and counted up to 0 again, then, it continues increasing in positive.

T2=1

T2-T1 = (0-999)

There's the negative duration and the bug I've already mentioned in every post where (T2<T1) and (T2>0)

I really don't want to explain it again. Just accept that I've provided a solution for those who want it.


Krischan2009
Use this check first to fix negative values

ms%=MilliSecs()
If ms<0 Then ms=ms And $7fffffff


_PJ_2009
. . .

That doesn't make the slightest difference.

I really, really mean this is the last time I will say this:

The problem doesn't involve negative values at all, only when
(T2<T1) and (T2>0)


TaskMaster2009
You are correct.

In the case that you are comparing two times that you got about 50 days apart, you have solved the problem. Except... You do get a positive value, but you do not get the actual difference in time. The result is going to be some arbitrary time.

But, I would hope that if you are comparing times that far apart, you would use time/date values rather than just a millisec counter. You are adding overhead to every millisecs check, just in case you make a check with numbers 50 days apart.


GfK2009
Wow. An argument in a code archive.

I'm afraid that Floyd is 99% correct. He would have been 100% correct if he'd said Abs(Abs(time2)-Abs(time1)). That way you still get the time difference between time1 and time2. Its the use of Abs() throughout that makes negative values irrelevant.

Auf wiedersehen.


TaskMaster2009
...


schilcote2010
And remember to practice safe secs().


Code Archives Forum