Просмотр полной версии : [Function] GetTickDiff - исправление проблемы переполнения для GetTickCount
Описание:
Функция для вычисления времени, прошедшего между двумя вызовами GetTickCount(), с учётом возможности переполнения переданных значений.
Параметры:
newtick - текущее значение времени
oldtick - предыдущее значение времени
Возвращаемое значение:
Функция возвращает время, прошедшее между двумя переданными в неё значениями.
Код:
stock GetTickDiff(newtick, oldtick)
{
return newtick - oldtick;
}
Примечания:
Всегда знал, что данный фикс уже существует и не испытывал надобности в его написании, но после изучения реализации, рекомендуемой в wiki (http://pastebin.com/BZyaJpzs), понял, что она работает не корректно. Создал Pull Request (https://github.com/Southclaw/ScavengeSurvive/pull/294) в репозитории автора этого фикса, в котором вы можете найти код теста и его результаты. Также актуальную версию функции можно найти на GitHubGist (https://gist.github.com/ziggi/5d7d8dc42f54531feba7ae924c608e73).
Пример использования:
static
LastShot[MAX_PLAYERS];
public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)
{
new
current_tick = GetTickCount();
interval = GetTickDiff(current_tick, LastShot[playerid]);
printf("Last shot interval: %i ms", interval);
LastShot[playerid] = current_tick;
return 1;
}
Автор: ziggi
Спасибо за фикс! Как раз изучал эту тему сейчас.
Можно, я думаю, добавить ссылку на гитхаб с ним(https://gist.github.com/ziggi/5d7d8dc42f54531feba7ae924c608e73) в тему, или исправить здесь код до актуального, т.к. я сначала увидел код по ссылке с Вики Самп, а затем в этой теме, и лишь ревизии гиста позволили мне понять, что там актуальный, а здесь нет.
Спасибо за фикс! Как раз изучал эту тему сейчас.
Можно, я думаю, добавить ссылку на гитхаб с ним(https://gist.github.com/ziggi/5d7d8dc42f54531feba7ae924c608e73) в тему, или исправить здесь код до актуального, т.к. я сначала увидел код по ссылке с Вики Самп, а затем в этой теме, и лишь ревизии гиста позволили мне понять, что там актуальный, а здесь нет.
Спасибо, забыл про эту тему совсем. Заметил, что в функции есть лишнее условие - обновил функцию ещё раз.
Daniel_Cortez
19.06.2018, 15:32
(cellmax - oldtick + 1) - (cellmin - newtick)
Вот это довольно интересное выражение. А интересно оно тем, что cellmax + 1 из-за целочисленного переполнения даёт cellmin и выражение можно записать так:
(cellmin - oldtick) - (cellmin - newtick)
Раскрываем скобки:
cellmin - oldtick - cellmin + newtick
Упрощаем (cellmin и -cellmin взаимоуничтожаются):
newtick - oldtick
Но стоп, это ведь тот же самый код, что и вне ветки if !
stock GetTickDiff(newtick, oldtick)
{
if (oldtick > newtick) {
return newtick - oldtick;
}
return newtick - oldtick;
}
Я что-то делаю не так? Очень хотелось бы узнать, чем вся эта функция лучше, чем просто newtick - oldtick.
UPD: Написал на скорую руку тест, чтобы выявить разницу в результатах между функцией и newtick - oldtick.
В нём производится перебор всего диапазона возможных значений oldtick, при этом newtick на 10 больше oldtick в первом цикле и на 10 меньше во втором. Если результаты функции и простого вычитания отличаются, в консоль выводится сообщение.
Также добавил вывод номеров итераций, кратных 100_000_000, чтобы убедиться, что код выполняется.
#include <a_samp>
stock GetTickDiff(newtick, oldtick)
{
if (oldtick > newtick)
{
return (cellmax - oldtick + 1) - (cellmin - newtick);
}
return newtick - oldtick;
}
#define GetTickDiff_simplified(%0,%1) ((%0)-(%1))
main()
{
printf("testing...");
static newtick = 10, oldtick = 0;
static diff1, diff2;
do {
if (oldtick % 100_000_000 == 0)
printf("%d", oldtick);
diff1 = GetTickDiff(newtick, oldtick);
diff2 = GetTickDiff_simplified(newtick, oldtick);
if (diff1 != diff2)
printf("result for (%d, %d) differ: %d, %d", newtick, oldtick, diff1, diff2);
} while ((++newtick, ++oldtick) != 0);
newtick = -10; // oldtick is already 0
do {
if (oldtick % 100_000_000 == 0)
printf("%d", oldtick);
diff1 = GetTickDiff(newtick, oldtick);
diff2 = GetTickDiff_simplified(newtick, oldtick);
if (diff1 != diff2)
printf("result for (%d, %d) differ: %d, %d", newtick, oldtick, diff1, diff2);
} while ((++newtick, ++oldtick) != 0);
printf("done");
}
Вывод:
testing...
0
100000000
200000000
300000000
400000000
500000000
600000000
700000000
800000000
900000000
1000000000
1100000000
1200000000
1300000000
1400000000
1500000000
1600000000
1700000000
1800000000
1900000000
2000000000
2100000000
-2100000000
-2000000000
-1900000000
-1800000000
-1700000000
-1600000000
-1500000000
-1400000000
-1300000000
-1200000000
-1100000000
-1000000000
-900000000
-800000000
-700000000
-600000000
-500000000
-400000000
-300000000
-200000000
-100000000
0
100000000
200000000
300000000
400000000
500000000
600000000
700000000
800000000
900000000
1000000000
1100000000
1200000000
1300000000
1400000000
1500000000
1600000000
1700000000
1800000000
1900000000
2000000000
2100000000
-2100000000
-2000000000
-1900000000
-1800000000
-1700000000
-1600000000
-1500000000
-1400000000
-1300000000
-1200000000
-1100000000
-1000000000
-900000000
-800000000
-700000000
-600000000
-500000000
-400000000
-300000000
-200000000
-100000000
done
Как видно, результаты идентичны, ни одного сообщения об отличии.
Да уж, забавно)) Обновил.
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot