Well in you ask the GetTickCount twice when calculating with it, so it allready passed the 50 when you calculate with it, however I didn't claim GetTickCount would be accurate!

[pascal]
i:=gettickcount;
while i+50 > gettickcount do begin
// Here you ask the new GetTickCount, which is allready higher than the one in the while function...
number:=gettickcount-i;
end;
showmessage(inttostr(number));
end;[/pascal]

GetTickCount, will never be accurate, but you didn't ask for an accurate timer, you asked for a timer that would work approx. the same on all machines, don't forget you are using a loop and a few statements, all those things take time. But what do you need it for? If you want to make a sprite move timed over the screen then there is no need for perfect accuracy!

If you want a faster more accurate timer use the timeGetTime function Useless Hacker suggested or you could write or use a third-party threaded-timer, however most threaded-timers I've seen use GetTickCount or timeGetTime in combination with a sleep internally!