Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 1 из 2 1 2 ПоследняяПоследняя
Показано с 1 по 10 из 12

Тема: GetNumberOfDigits

  1. #1
    Аватар для VVWVV
    ?

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±

    GetNumberOfDigits

    Описание:
    Вычисляет длину числа. Данная функция может работать с отрицательными и положительными числами.

    Параметры:
    number - число

    Возвращаемое значение:
    Возвращает длину числа.

    Плюсы реализации:
    • Быстрое вычисление длины числа (тесты).

    Код:
    Реализация с использованием __emit (требуется компилятор версии 3.10.6 или новее):
      Открыть/закрыть
    1. stock GetNumberOfDigits(number)
    2. { // by Daniel_Cortez \\ pro-pawn.ru
    3. __emit
    4. {
    5. load.s.pri number
    6. zero.alt
    7. jsgeq check1
    8. move.alt
    9. eq.c.pri cellmin
    10. add
    11. neg
    12. check1:
    13. const.alt 1_000_000
    14. jsgeq check2
    15. const.alt 100
    16. jsgeq check1_2
    17. const.alt 10
    18. sgeq
    19. inc.pri
    20. retn
    21. check1_2:
    22. const.alt 10_000
    23. jsgeq check1_3
    24. const.alt 1_000
    25. sgeq
    26. add.c 3
    27. retn
    28. check1_3:
    29. const.alt 100_000
    30. sgeq
    31. add.c 5
    32. retn
    33. check2:
    34. const.alt 100_000_000
    35. jsgeq check3
    36. const.alt 10_000_000
    37. sgeq
    38. add.c 7
    39. retn
    40. check3:
    41. const.alt 1_000_000_000
    42. sgeq
    43. }
    44. return __emit add.c 9;
    45. }

    Реализация без __emit (подходит для более старых версий компилятора, но работает медленнее):
      Открыть/закрыть
    1. stock GetNumberOfDigits(number)
    2. { // by Daniel_Cortez \\ pro-pawn.ru
    3. if (number < 0)
    4. number = -(number + _:(number == cellmin));
    5. if (number < 100_000)
    6. {
    7. if (number < 100)
    8. return 1 + _:(number >= 10);
    9. if (number < 10_000)
    10. return 3 + _:(number >= 1_000);
    11. return 5;
    12. }
    13. if (number < 10_000_000)
    14. return 6 + _:(number >= 1_000_000);
    15. if (number < 1_000_000_000)
    16. return 8 + _:(number >= 100_000_000);
    17. return 10;
    18. }


    Пример использования:
    1. main()
    2. {
    3. // Выведет только 10
    4. printf("%d", GetNumberOfDigits(1000000000));
    5. }

    См. также:

    Автор: Daniel_Cortez

    Исключительно для pro-pawn.ru

    Копирование данной статьи на других ресурсах без разрешения автора запрещено.
    Последний раз редактировалось Daniel_Cortez; 21.12.2019 в 14:13. Причина: добавил версию с __emit

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

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    ИМХО, было бы корректнее использовать название "GetNumberDecimalDigits" или "GetNumberDecimalPositions". Слово "Size" в названиях обычно используют, когда функция возвращает размер чего-то: массива или активных ячеек в пуле (pool), поэтому название "GetNumberSize" звучит контринтуитивно.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  3. #3
    Аватар для VVWVV
    ?

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    ИМХО, было бы корректнее использовать название "GetNumberDecimalDigits" или "GetNumberDecimalPositions". Слово "Size" в названиях обычно используют, когда функция возвращает размер чего-то: массива или активных ячеек в пуле (pool), поэтому название "GetNumberSize" звучит контринтуитивно.
    Да, наверное. Дабы не запоминать большие названия можно воспользоваться вариантом "GetNumberOfDigits". Я же опирался на быстроту написания, а также на читаемость в коде.
    Последний раз редактировалось VVWVV; 10.12.2016 в 09:25.

  4. #4
    Аватар для VVWVV
    ?

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±
    Обновил реализацию функции.

  5. #5
    Аватар для MassonNN
    Пользователь

    Статус
    Оффлайн
    Регистрация
    16.03.2018
    Адрес
    Москва
    Сообщений
    129
    Репутация:
    6 ±
    какой смысл в return 10, если максимальное положительное значение int это 2147483647
    (я могу ошибаться и сто процентов ошибаюсь, поэтому и пишу)

  6. #6
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от MassonNN Посмотреть сообщение
    какой смысл в return 10, если максимальное положительное значение int это 2147483647
    (я могу ошибаться и сто процентов ошибаюсь, поэтому и пишу)
    Эмм, ну так посчитай количество символов в числе "2.147.483.647".
    Максимальное число, отсекаемое условием:
    1. if (number < 1_000_000_000)

    и 2147483647 в него не входит. Тогда и будет возвращено 10.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

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

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Решил немного поэкспериментировать с оператором __emit, получилось следующее:
    1. stock GetNumberOfDigits(number)
    2. {
    3. __emit
    4. {
    5. load.s.pri number
    6. zero.alt
    7. jsgeq check1
    8. move.alt
    9. eq.c.pri cellmin
    10. add
    11. neg
    12. check1:
    13. const.alt 1_000_000
    14. jsgeq check2
    15. const.alt 100
    16. jsgeq check1_2
    17. const.alt 10
    18. sgeq
    19. inc.pri
    20. retn
    21. check1_2:
    22. const.alt 10_000
    23. jsgeq check1_3
    24. const.alt 1_000
    25. sgeq
    26. add.c 3
    27. retn
    28. check1_3:
    29. const.alt 100_000
    30. sgeq
    31. add.c 5
    32. retn
    33. check2:
    34. const.alt 100_000_000
    35. jsgeq check3
    36. const.alt 10_000_000
    37. sgeq
    38. add.c 7
    39. retn
    40. check3:
    41. const.alt 1_000_000_000
    42. sgeq
    43. }
    44. return __emit add.c 9;
    45. }

    Если хотите самостоятельно перепроверить корректность функции, то вот тест, который проверяет работу функции на всех возможных в Pawn целочисленных значениях (включая предельные cellmin и cellmax):
      Открыть/закрыть
    1. Test(min, max, num)
    2. {
    3. static i;
    4. printf("testing %d..%d ...", min, max);
    5. i = min;
    6. do {
    7. if (GetNumberOfDigits(i) != num)
    8. printf("Error: %d -> %d", i, GetNumberOfDigits(i));
    9. if (i == cellmax)
    10. break;
    11. } while (i != cellmax && ++i <= max);
    12. print("... Done!");
    13. }
    14.  
    15. main()
    16. {
    17. Test(cellmin, -1000000000, 10);
    18. Test(-999999999, -100000000, 9);
    19. Test(-99999999, -10000000, 8);
    20. Test(-9999999, -1000000, 7);
    21. Test(-999999, -100000, 6);
    22. Test(-99999, -10000, 5);
    23. Test(-9999, -1000, 4);
    24. Test(-999, -100, 3);
    25. Test(-99, -10, 2);
    26. Test(-9, 9, 1);
    27. Test(10, 99, 2);
    28. Test(100, 999, 3);
    29. Test(1000, 9999, 4);
    30. Test(10000, 99999, 5);
    31. Test(100000, 999999, 6);
    32. Test(1000000, 9999999, 7);
    33. Test(10000000, 99999999, 8);
    34. Test(100000000, 999999999, 9);
    35. Test(1000000000, cellmax, 10);
    36. }


    И тесты производительности (примечание: в варианты от DeimoS'а и VVWVV я добавил проверку на cellmin, чтобы уравнять их в корректности работы):
      Открыть/закрыть
    PHP код:
    /*======== Настройки =========================================================*/
    #include <float>

    const PROFILER_ITERATIONS_MAJOR 1_000;//100_000;
    const PROFILER_ITERATIONS_MINOR 1_000;//10;

    new const code_snippets_names[5][] =
    {
        {
    "VVWVV"},
        {
    "DeimoS(1)"},
        {
    "DeimoS(2)"},
        {
    "Daniel_Cortez"},
        {
    "Daniel_Cortez (__emit)"}
    };

    stock GetNumberOfDigits_VVWVV({Float,_}:number)
    {
        return 
    number != floatround(floatlog(floatabs(number))) + 1;
    }

    stock GetCountsOfDigits_DeimoS(number)
    {
        if (
    number 0)
            
    number = -(number _:(number == cellmin));
        if (
    number 100_000)
        {
            if(
    number 100)
            {
                if(
    number 10)
                    return 
    1;
                else
                    return 
    2;
            }
            else
            {
                if(
    number 1_000)
                    return 
    3;
                else
                {
                    if(
    number 10_000)
                        return 
    4;
                    else
                        return 
    5;
                }
            }
        }
        else
        {
            if(
    number 10_000_000)
            {
                if(
    number 1_000_000)
                    return 
    6;
                else
                    return 
    7;
            }
            else
            {
                if(
    number 100_000_000)
                    return 
    8;
                else
                {
                    if(
    number 1_000_000_000)
                        return 
    9;
                    else
                        return 
    10;
                }
            }
        }
    }

    stock GetCountsOfDigits_DeimoS2(number)
    {
        if(
    number 0)
        {
            if (
    number > -100_000)
            {
                if (
    number > -100)
                    return 
    _:(number <= -10);
                if (
    number > -10_000)
                    return 
    _:(number <= -1_000);
                return 
    5;
            }
            if (
    number > -10_000_000)
                return 
    _:(number <= -1_000_000);
            if (
    number > -1_000_000_000)
                return 
    _:(number <= -100_000_000);
            return 
    10;
        }
        else
        {
            if (
    number 100_000)
            {
                if (
    number 100)
                    return 
    _:(number >= 10);
                if (
    number 10_000)
                    return 
    _:(number >= 1_000);
                return 
    5;
            }
            if (
    number 10_000_000)
                return 
    _:(number >= 1_000_000);
            if (
    number 1_000_000_000)
                return 
    _:(number >= 100_000_000);
            return 
    10;
        }
    }

    stock GetNumberOfDigits_DC(number)
    {
        if (
    number 0)
            
    number = -(number _:(number == cellmin));
        if (
    number 100_000)
        {
            if (
    number 100)
                return 
    _:(number >= 10);
            if (
    number 10_000)
                return 
    _:(number >= 1_000);
            return 
    5;
        }
        if (
    number 10_000_000)
            return 
    _:(number >= 1_000_000);
        if (
    number 1_000_000_000)
            return 
    _:(number >= 100_000_000);
        return 
    10;
    }

    stock GetNumberOfDigits_DC__emit(number)
    {
        
    __emit
        
    {
            
    load.s.pri number
            zero
    .alt
            jsgeq check1
            move
    .alt
            eq
    .c.pri cellmin
            add
            neg
        check1
    :
            const.
    alt 1_000_000
            jsgeq check2
            
    const.alt 100
            jsgeq check1_2
            
    const.alt 10
            sgeq
            inc
    .pri
            retn
        check1_2
    :
            const.
    alt 10_000
            jsgeq check1_3
            
    const.alt 1_000
            sgeq
            add
    .c 3
            retn
        check1_3
    :
            const.
    alt 100_000
            sgeq
            add
    .c 5
            retn
        check2
    :
            const.
    alt 100_000_000
            jsgeq check3
            
    const.alt 10_000_000
            sgeq
            add
    .c 7
            retn
        check3
    :
            const.
    alt 1_000_000_000
            sgeq
        
    }
        return 
    __emit add.c 9;
    }

    // 0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -20, 30, ..., 1_000_000_000, -2_000_000_000
    static numbers[3];

    #define Prerequisites(); \
        
    numbers[0] = 0; \
        for (new 
    0inc 119; ++iinc *= 10) \
            for (new 
    110; ++j+= inc) \
                
    numbers[j] = * (((j) & 1) * -1); \
        
    numbers[82] = 1_000_000_000; \
        
    numbers[83] = -2_000_000_000; \
        static 
    i;

    #define CodeSnippet0(); \
        
    for (0sizeof(numbers); ++i) \
            
    GetNumberOfDigits_VVWVV(numbers[i]);

    #define CodeSnippet1(); \
        
    for (0sizeof(numbers); ++i) \
            
    GetCountsOfDigits_DeimoS(numbers[i]);

    #define CodeSnippet2(); \
        
    for (0sizeof(numbers); ++i) \
            
    GetCountsOfDigits_DeimoS2(numbers[i]);

    #define CodeSnippet3(); \
        
    for (0sizeof(numbers); ++i) \
            
    GetNumberOfDigits_DC(numbers[i]);

    #define CodeSnippet4(); \
        
    for (0sizeof(numbers); ++i) \
            
    GetNumberOfDigits_DC__emit(numbers[i]);
    /*======== Конец настроек ===================================================*/ 
    Код:
    Тестирование: 5 отрывков кода.
    Режим: интерпретируемый, 1000x1000 итераций.
    VVWVV: 51195
    DeimoS(1): 21594
    DeimoS(2): 19095
    Daniel_Cortez: 20902
    Daniel_Cortez (__emit): 15849
    
    Тестирование: 5 отрывков кода.
    Режим: с JIT-компиляцией, 1000x1000 итераций.
    VVWVV: 16583
    DeimoS(1): 1523
    DeimoS(2): 1395
    Daniel_Cortez: 1677
    Daniel_Cortez (__emit): 1373
    Number of vehicle models: 0
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  8. #8
    Аватар для MassonNN
    Пользователь

    Статус
    Оффлайн
    Регистрация
    16.03.2018
    Адрес
    Москва
    Сообщений
    129
    Репутация:
    6 ±
    Интересно можно ли через emit узнать сколько битов забито числами и просто выдавать результат, или же это не реализуемо?

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

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от MassonNN Посмотреть сообщение
    Интересно можно ли через emit узнать сколько битов забито числами и просто выдавать результат, или же это не реализуемо?
    Кол-во установленных битов != кол-во цифр в числе.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  10. #10
    Аватар для MassonNN
    Пользователь

    Статус
    Оффлайн
    Регистрация
    16.03.2018
    Адрес
    Москва
    Сообщений
    129
    Репутация:
    6 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Кол-во установленных битов != кол-во цифр в числе.
    Ну подсчитать то можно, наверное?)))


    Ещё есть такой вариант:

    Код HTML:
    mov eax,10
    cmp ecx,10^9
    sbb eax,0
    cmp ecx,10^8
    sbb eax,0
    ....
    cmp ecx,10^2
    sbb eax,0
    cmp ecx,10^1
    sbb eax,0
    ecx - число N, eax - количество цифр в числе.
    1

 

 
Страница 1 из 2 1 2 ПоследняяПоследняя

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

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

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

Ваши права

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