Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 5 из 5
  1. #1
    Аватар для ziggi
    Проверенный

    Статус
    Оффлайн
    Регистрация
    14.05.2015
    Сообщений
    1,181
    Репутация:
    790 ±

    GetTickDiff - исправление проблемы переполнения для GetTickCount

    Описание:
    Функция для вычисления времени, прошедшего между двумя вызовами GetTickCount(), с учётом возможности переполнения переданных значений.

    Параметры:
    newtick - текущее значение времени
    oldtick - предыдущее значение времени

    Возвращаемое значение:
    Функция возвращает время, прошедшее между двумя переданными в неё значениями.

    Код:
    1. stock GetTickDiff(newtick, oldtick)
    2. {
    3. return newtick - oldtick;
    4. }

    Примечания:
    • Всегда знал, что данный фикс уже существует и не испытывал надобности в его написании, но после изучения реализации, рекомендуемой в wiki, понял, что она работает не корректно. Создал Pull Request в репозитории автора этого фикса, в котором вы можете найти код теста и его результаты. Также актуальную версию функции можно найти на GitHubGist.

    Пример использования:
    1. static
    2. LastShot[MAX_PLAYERS];
    3.  
    4. public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)
    5. {
    6. new
    7. current_tick = GetTickCount();
    8. interval = GetTickDiff(current_tick, LastShot[playerid]);
    9.  
    10. printf("Last shot interval: %i ms", interval);
    11.  
    12. LastShot[playerid] = current_tick;
    13. return 1;
    14. }


    Автор: ziggi
    Последний раз редактировалось ziggi; 20.06.2018 в 18:00.

  2. Пользователь сказал cпасибо:
    DCPSHER (18.06.2018)
  3. #2
    Аватар для DCPSHER
    Пользователь

    Статус
    Оффлайн
    Регистрация
    14.05.2018
    Сообщений
    16
    Репутация:
    2 ±
    Спасибо за фикс! Как раз изучал эту тему сейчас.

    Можно, я думаю, добавить ссылку на гитхаб с ним(https://gist.github.com/ziggi/5d7d8d...a7ae924c608e73) в тему, или исправить здесь код до актуального, т.к. я сначала увидел код по ссылке с Вики Самп, а затем в этой теме, и лишь ревизии гиста позволили мне понять, что там актуальный, а здесь нет.

  4. Пользователь сказал cпасибо:
    ziggi (19.06.2018)
  5. #3
    Аватар для ziggi
    Проверенный

    Статус
    Оффлайн
    Регистрация
    14.05.2015
    Сообщений
    1,181
    Репутация:
    790 ±
    Цитата Сообщение от DCPSHER Посмотреть сообщение
    Спасибо за фикс! Как раз изучал эту тему сейчас.

    Можно, я думаю, добавить ссылку на гитхаб с ним(https://gist.github.com/ziggi/5d7d8d...a7ae924c608e73) в тему, или исправить здесь код до актуального, т.к. я сначала увидел код по ссылке с Вики Самп, а затем в этой теме, и лишь ревизии гиста позволили мне понять, что там актуальный, а здесь нет.
    Спасибо, забыл про эту тему совсем. Заметил, что в функции есть лишнее условие - обновил функцию ещё раз.

  6. #4
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от ziggi Посмотреть сообщение
    1. (cellmax - oldtick + 1) - (cellmin - newtick)
    Вот это довольно интересное выражение. А интересно оно тем, что cellmax + 1 из-за целочисленного переполнения даёт cellmin и выражение можно записать так:
    1. (cellmin - oldtick) - (cellmin - newtick)

    Раскрываем скобки:
    1. cellmin - oldtick - cellmin + newtick

    Упрощаем (cellmin и -cellmin взаимоуничтожаются):
    1. newtick - oldtick

    Но стоп, это ведь тот же самый код, что и вне ветки if !
    1. stock GetTickDiff(newtick, oldtick)
    2. {
    3. if (oldtick > newtick) {
    4. return newtick - oldtick;
    5. }
    6. return newtick - oldtick;
    7. }

    Я что-то делаю не так? Очень хотелось бы узнать, чем вся эта функция лучше, чем просто newtick - oldtick.



    UPD: Написал на скорую руку тест, чтобы выявить разницу в результатах между функцией и newtick - oldtick.
    В нём производится перебор всего диапазона возможных значений oldtick, при этом newtick на 10 больше oldtick в первом цикле и на 10 меньше во втором. Если результаты функции и простого вычитания отличаются, в консоль выводится сообщение.
    Также добавил вывод номеров итераций, кратных 100_000_000, чтобы убедиться, что код выполняется.
      Открыть/закрыть
    PHP код:
    #include <a_samp>

    stock GetTickDiff(newtickoldtick)
    {
        if (
    oldtick newtick)
        {
            return (
    cellmax oldtick 1) - (cellmin newtick);
        }
        return 
    newtick oldtick;
    }

    #define GetTickDiff_simplified(%0,%1) ((%0)-(%1))

    main()
    {
        
    printf("testing...");
        static 
    newtick 10oldtick 0;
        static 
    diff1diff2;
        do {
            if (
    oldtick 100_000_000 == 0)
                
    printf("%d"oldtick);
            
    diff1 GetTickDiff(newtickoldtick);
            
    diff2 GetTickDiff_simplified(newtickoldtick);
            if (
    diff1 != diff2)
                
    printf("result for (%d, %d) differ: %d, %d"newtickoldtickdiff1diff2);
        } while ((++
    newtick, ++oldtick) != 0);
        
    newtick = -10// oldtick is already 0
        
    do {
            if (
    oldtick 100_000_000 == 0)
                
    printf("%d"oldtick);
            
    diff1 GetTickDiff(newtickoldtick);
            
    diff2 GetTickDiff_simplified(newtickoldtick);
            if (
    diff1 != diff2)
                
    printf("result for (%d, %d) differ: %d, %d"newtickoldtickdiff1diff2);
        } 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

    Как видно, результаты идентичны, ни одного сообщения об отличии.
    Последний раз редактировалось Daniel_Cortez; 19.06.2018 в 16:10. Причина: добавил тест
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  7. #5
    Аватар для ziggi
    Проверенный

    Статус
    Оффлайн
    Регистрация
    14.05.2015
    Сообщений
    1,181
    Репутация:
    790 ±
    Да уж, забавно)) Обновил.

 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •