PDA

Просмотр полной версии : [Вопрос] Как максимально быстро узнать название месяца.



Иван Бубнов
17.01.2016, 14:56
Я вас что? Да, категорический приветствую.
Собственно вопрос написан в названии темы.


GetMonthName(month)
{
new mname[12];
switch(month)
{
case 1: format(mname, sizeof(mname), "Января");
//....куча говнокода
}
return mname;
}

А также...


stock GetMonthName()
{
new name[32];
new year,month,day;
getdate(year, month, day);
switch(month)
{
case 1: format(name,32,"Январь");
case 2: format(name,32,"Февраль");
case 3: format(name,32,"Март");
case 4: format(name,32,"Апрель");
case 5: format(name,32,"Май");
case 6: format(name,32,"Июнь");
case 7: format(name,32,"Июль");
case 8: format(name,32,"Август");
case 9: format(name,32,"Сентябрь");
case 10: format(name,32,"Октябрь");
case 11: format(name,32,"Ноябрь");
case 12: format(name,32,"Декабрь");
}
return name;
}

ziggi
17.01.2016, 15:37
static gMonthNames[][9] = {
"Январь",
"Февраль",
"Март",
"Апрель",
"Май",
"Июнь",
"Июль",
"Август",
"Сентябрь",
"Октябрь",
"Ноябрь",
"Декабрь"
};

stock GetMonthName(month, name[], const size = sizeof(name))
{
if (month < 1 || month > sizeof(gMonthNames) + 1) {
return 0;
}

name[0] = '\0';
strcat(name, gMonthNames[month - 1], size);

return 1;
}

stock GetCurrentMonthName(name[], const size = sizeof(name))
{
new month;
getdate(_, month, _);

name[0] = '\0';
strcat(name, gMonthNames[month - 1], size);
}

stock ReturnMonthName(month)
{
if (month < 0 || month > sizeof(gMonthNames)) {
return 0;
}

return gMonthNames[month - 1];
}

stock ReturnCurrentMonthName()
{
new month;
getdate(_, month, _);

return gMonthNames[month - 1];
}

Daniel_Cortez
17.01.2016, 15:39
stock GetMonthName(number, name[], size = sizeof(name))
{
static const month_names[12][] =
{
!"January", !"February", !"March", !"April", !"May", !"June",
!"July", !"August", !"September", !"October", !"November", !"December"
};
if (1 <= number <= sizeof(month_names))
return strunpack(name, month_names[number - 1], size);
return 0;
}

ziggi
17.01.2016, 15:51
stock GetMonthName(number, name[], size = sizeof(name))
{
static const month_names[12][] =
{
!"January", !"February", !"March", !"April", !"May", !"June",
!"July", !"August", !"September", !"October", !"November", !"December"
};
if (1 <= number <= sizeof(month_names))
return strunpack(name, month_names[number - 1], size);
return 0;
}


Без упаковки будет быстрее, имхо.

P.S. Человек с lightcode проводил тесты условий, вот какие он результаты получил (я лично не проверял):


3285 - a < b < c
2478 a < b && b < c
4947 IS_IN_RANGE



#define IS_IN_RANGE(%0,%1,%2) (((%0) - ((%1) + cellmin)) < (((%2) + 1) - ((%1) + cellmin)))

Иван Бубнов
17.01.2016, 16:38
Close.

Daniel_Cortez
18.01.2016, 17:00
Не люблю заниматься некропостингом, но многие факты в предыдущем посте показались мне не совсем понятными.



Без упаковки будет быстрее, имхо.
http://pro-pawn.ru/showthread.php?12585


/*======== Настройки =========================================================*/
const PROFILER_ITERATIONS_MAJOR = 1_000_000;
const PROFILER_ITERATIONS_MINOR = 100;

new const code_snippets_names[][] =
{
{"strcat"},
{"strunpack"},
{"memcpy"}
};

#define Prerequisites();\
static const UNPACKED_STR[] = "Sample text";\
static const PACKED_STR[] = !"Sample text";\
new buffer[32];

#define CodeSnippet0();\
buffer[0] = '\0', strcat(buffer, UNPACKED_STR);

#define CodeSnippet1();\
strunpack(buffer, PACKED_STR);

#define CodeSnippet2();\
memcpy(buffer, PACKED_STR, 0, sizeof(UNPACKED_STR) * (cellbits / charbits));
/*======== Конец настроек ===================================================*/



Тестирование: 3 отрывка кода.
Режим: интерпретируемый, 1000000x100 итераций.
strcat: 14111
strunpack: 12558
memcpy: 13253



Тестирование: 3 отрывка кода.
Режим: с JIT-компиляцией, 1000000x100 итераций.
strcat: 9460
strunpack: 11608
memcpy: 7433

Как видно, при интерпретации быстрее strunpack, а с JIT - memcpy.
Мало того, можно заставить memcpy работать c JIT ещё быстрее, сделав вместо вызова нативной функции подстановку процессорных инструкций - функция сравнительно простая для этого.
Но я всё же выбрал strunpack, как компромисс между скоростью выполнения и компактностью данных. Алгоритм не такой уж и сложный (всего-то вызов одной функции), чтобы производительность была в приоритете.



Человек с lightcode проводил тесты условий, вот какие он результаты получил (я лично не проверял):


3285 - a < b < c
2478 a < b && b < c
4947 IS_IN_RANGE



#define IS_IN_RANGE(%0,%1,%2) (((%0) - ((%1) + cellmin)) < (((%2) + 1) - ((%1) + cellmin)))

ИМХО, вопрос спорный, т.к. результат может зависеть от вероятности вхождения/не вхождения числа в заданный диапазон и от использования JIT.
Одним тестом тут вряд ли обойдёшься (кстати, тебе показывали код теста?), следует оптимизировать код, исходя из ситуации. Причём, нужно хорошо знать, в какие инструкции AMX превратится код на Pawn, чтобы быть уверенным в эффективности оптимизации.
Например, можно сделать проверку даже так:


stock IsInRange(x, a, b)
{
if (a <= x)
if (x <= b)
return 1;
return 0;
}



/*======== Настройки =========================================================*/
const PROFILER_ITERATIONS_MAJOR = 1_000_000;
const PROFILER_ITERATIONS_MINOR = 100;

new const code_snippets_names[2][] =
{
{"if (RANGE_BEGIN <= j <= RANGE_END)"},
{"if (RANGE_BEGIN <= j && j <= RANGE_END)"},
{"if (RANGE_BEGIN <= j) if (j <= RANGE_END)"}
};

#define Prerequisites();\
const RANGE_BEGIN = 1;\
const RANGE_END = PROFILER_ITERATIONS_MINOR / 2;

DoNothing()
{
#emit retn
}

#define CodeSnippet0();\
if (RANGE_BEGIN <= j <= RANGE_END) DoNothing();

#define CodeSnippet1();\
if (RANGE_BEGIN <= j && j <= RANGE_END) DoNothing();

#define CodeSnippet2();\
if (RANGE_BEGIN <= j) if (j <= RANGE_END) DoNothing();
/*======== Конец настроек ===================================================*/



Тестирование 3 отрывка кода.
Режим: интерпретируемый, 1000000x1000 итераций.
if (RANGE_BEGIN <= j <= RANGE_END): 59765
if (RANGE_BEGIN <= j && j <= RANGE_END): 70405
if (RANGE_BEGIN <= j) if (j <= RANGE_END): 51045



Тестирование 3 отрывка кода.
Режим: с JIT-компиляцией, 10000000x1000 итераций.
if (RANGE_BEGIN <= j <= RANGE_END): 74329
if (RANGE_BEGIN <= j && j <= RANGE_END): 67290
if (RANGE_BEGIN <= j) if (j <= RANGE_END): 65299

Как видно, предложенный способ с разбиением на два if быстрее как с JIT, так и без.
Правда, такое разбиение ветвлений на два может не подойти для случаев, когда в одном исходном if есть ветвь else, но выполняться такой код будет немного быстрее.
И, как я говорил ранее, в разных ситуациях код может быть разным. В данном тесте вероятность вхождения числа в диапазон 50%, но в реальных ситуациях эта вероятность может зависеть от всего, даже от расположения звёзд, поэтому сей тест нельзя считать однозначным ответом на вопрос о методах проверки на вхождение на диапазон, равно как и другие аналогичные тесты.