Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Bug in SECONDS() ????

Status
Not open for further replies.

Kimed

Programmer
May 25, 2005
104
LT
Hi,

Some time ago I found a certain code sample for VFP that would generate unique keys based on (among other things) value returned by system timer. I tried to modify it for usage in FP 2.6 and was quite happy with it... until a couple of weeks later I found that generated keys aren't that unique as I thought (fortunately it happened *before* I reported that the program is ready :D). Looking for any possible bugs in places I won't bother you with, I finally got down to the core of things and wrote the following test program:

create cursor dummy ( num n(4), tim n(8) )
for i=1 to 9999
insert into dummy values ( i, seconds()*1000 )
next

Supposedly the order of two fields had to be identical (or at least have identical "tim" in adjacent "num" records, but nothing worse). In fact, after indexing the cursor I got something like this:

Num ?Tim
?????????????
10?56599569 <==
11?56599571 <==
1?56599601
2?56599604
3?56599607
4?56599609
5?56599612
6?56599614
7?56599617
8?56599619
9?56599621
14?56599625 <==
12?56599654
13?56599656
15?56599693
16?56599718
17?56599744
18?56599769
19?56599771
22?56599790 <==
20?56599795
...

What could be a reason for it? I'm running FP 2.6 on Windows XP SP2, if it matters.

Thanks.
 
You don't say exactly which algorthm you're using to get the unique value. Are you just using the result from the SECONDS function or are you processing it in some way?

I would be more inclined to suspect a bug in the INSERT command. It's supposed to insert at the end of the table but you're doing it in such a tight loop that the various buffers might be getting confused and not inserting the records in the same order that they are being created.

Try repeating the test but put the values into an array instead.

You could try using SYS(2015) to generate a unique random ID instead.

Geoff Franklin
 
Of course, the algorithm is much more complex than just taking seconds. It involves Julian day, time (both of which can be extracted from the key), a 0-99 counter that is just supposed to overcome collisions of too fast generation, a comp's ID in the network and a packaging algorithm that places it all into a neat 8-byte code. Only that in the process of testing I've been stripping it down more and more, taking simpler formulas and getting the same incorrect result, until I bumped onto something that I couldn't explain.

(In VFP it all worked impeccably, mind you)

Oh well, thanks for the idea with logging into array. It was quite frustrating not to be able to use debugger.
 
Is there a reason you're generating unique keys instead of just storing the last key in a table and looking it up? Doing it with a table ensures that you always get a new value.

Tamar
 
I was encountered this problem long time ago running Win 98 SE and was looking for some
answers and found that it is because of running FP 2.6 on multitasking OS.
It will always do that errors with SECONDS() function. So you have to go different way.

Zhavic

---------------------------------------------------------------
In the 1960s you needed the power of two Comodore64s to get a rocket to the moon. Now you need a machine which is a vast number of times more powerful just to run the most popular GUI.
 
Same here with FPD 2.5 and Windows XP SP2. Something I noticed during testing is that Windows does some fancy tricks with the clock for DOS programs. It will only change the time in a DOS window when a program is launched or quit. Norton Commander and FOX both display a clock. If I change the time from the system tray, the NC clock and the Fox clock do not change until I load or quit FOX. A continuous run of any DOS program gets a consistent clock.

Code:
set talk off
create cursor dummy ( num n(4), tim n(8) )
pa=0
retry=0
for i=1 to 9999
  a=int(seconds()*1000)
  * a<pa, Bad Values shows how often the timer goes below it's previous value on each run
  * a<=pa ensures unique ascending values eliminating the need for "num n(4)"
  do while a<=pa and not (a<10000000 and pa>80000000)
    retry=retry+1
    a=int(seconds()*1000)
  enddo
  pa=a
  insert into dummy values ( i, a )
next
go top
?retry,"Bad Values"
*clos data

What's funny is that the same problem does not occur with GWBasic. It always shows 0 Retries.

Code:
10 PA=0
20 RETRY=0
30 FOR I=1 TO 10000
40 A=INT(TIMER*1000)
50 WHILE A<PA
60 A=INT(TIMER*1000)
70 RETRY=RETRY+1
80 WEND
90 PA=A
100 PRINT A
110 NEXT I
120 PRINT RETRY,"Retries"

 
Is there a reason you're generating unique keys instead of just storing the last key in a table and looking it up?

Well, I just liked the idea that the record creation date/time is automatically encoded in the key itself and can be extracted from it... since it is not *really* crucial, I may resort to table-based keys, but now as I can see the inside mechanics better, I may yet give it one more try just out of stubbornness ;) .

Thanks everybody.
 
There is an issue with the SECONDS command in which it isn't very accurate. Instead use the TIME command, and convert the time into seconds with a simple algorithm.

Hope this helps.

B"H
Brak
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top