 Rules FAQ Members List Search Register Login Raised This Month: \$60 Target: \$400 15%

Author Message
Siveroo
Junior Member
Join Date: Apr 2020  10-13-2020 , 11:10   Which method is more efficient? #1 i have two functions that will generate a random xy coordinate within a certain radius, i don't really care about uniform distribution or something like that. which one of these function is more efficient, and why? or maybe you can show me another code that's actually more efficient than these two codes. Btw, i don't care about the whether result being a float or an integer, i will use the coordinate both as a float and an integer later in my code Code: ```stock random_coord(coord, range) {     new newCoord;             newCoord = coord + random_num(-range, range);     newCoord = coord + random_num(-range, range);         while ( get_distance(iOrigin, Origin) > range ) {         newCoord = coord + random_num(-range, range);         newCoord = coord + random_num(-range, range);     doSomething(newCoord);     doSomething(newCoord); }``` Code 2: Code: ```stock random_coord(Origin, range){     new Float:rand_coord     new Float:theta     new Float:r     new Float:rand             rand = random_float(0.0, 1.0);   //randomize the smaller radius     rand = random_float(0.0, 1.0);   //randomize the angle multiplication factor     r = FLAME_RADIUS * rand     theta = rand * 6                 // i use 6 instead of 2*PI , don't judge me (dont really need extra accuracy)     rand_coord = r*floatcos(theta, radian)     rand_coord = r*floatsin(theta, radian)        doSomething(Origin + rand_coord);     doSomething(Origin + rand_coord); }``` Note : there might be some error, but i hope you can understand how each code works Last edited by Siveroo; 10-13-2020 at 11:13.  Natsheh
Veteran Member
Join Date: Sep 2012  10-13-2020 , 15:01   Re: Which method is more efficient? #2 PHP Code: ``` random_coord_within_region(Float:x, Float:y, radius=5.0, Float:random_coord){   random_coord = random_float(-radius, radius) + x;   random_coord = random_float(-radius, radius) + y;}  ``` shouldn't be so complicated. __________________ @User Tag Prefix 100% done ! @Mystery Box 100% done ! @VIP System 100% done ! Last edited by Natsheh; 10-13-2020 at 15:02.  Siveroo
Junior Member
Join Date: Apr 2020  10-14-2020 , 00:50   Re: Which method is more efficient? #3

Quote:
 Originally Posted by Natsheh PHP Code: ``` random_coord_within_region(Float:x, Float:y, radius=5.0, Float:random_coord) {    random_coord = random_float(-radius, radius) + x;    random_coord = random_float(-radius, radius) + y; }  ``` shouldn't be so complicated.
but i think that will result in a rectangular region instead of a circle  Black Rose
Veteran Member
Join Date: Feb 2011
Location: Upplands Väsby, Sweden  10-15-2020 , 14:50   Re: Which method is more efficient? #4 Code: ```stock random_coord1(coord, range) {     new newCoord, tempCoord;     tempCoord = coord;     tempCoord = coord;     do {         newCoord = tempCoord + random_num(-range, range);         newCoord = tempCoord + random_num(-range, range);     }     while ( get_distance(newCoord, tempCoord) > range ) }``` I don't understand the second code so I'm not sure if it's correct. That itself should be a reason to chose the first code. But the first code is faster as well. Spoiler Code: ```#include /* Measures the actual time (even if the server is frozen due to working) for up to almost 25d. new hTimer = TimerStart(); // ... TimerStop(hTimer); */ #define TimerStart()            tickcount() #define TimerMid(%0)            ( tickcount() - %0 ) #define TimerStop(%0)         ( %0 = tickcount() - %0 ) #define TimerDays(%0)         ( %0 / 86400000 ) #define TimerHours(%0)      ( %0 % 86400000 / 3600000 ) #define TimerMinutes(%0)        ( %0 % 3600000 / 60000 ) #define TimerSeconds(%0)        ( %0 % 60000 / 1000 ) #define TimerMilliseconds(%0)   ( %0 % 1000 ) /* TimerFormat(hTimer, output[], maxlen, mode = 1, bool:full = 0) * Formats the result of a timer handle into a string. * * Parameters: * * hTimer *    Timer Handle * * output[] *    The output string * * maxlen *    Maximum size of the output string * * mode *    1: 00:00:00:00.000 *    2: 0d 0h 0m 0s 0ms * * bool:full *    If full is set to true it will print all fields, even those which contains no value. *    If full is set to false and mode is set to 1, it will print the first field that contains a value and everything after that point. For example: 03:00:00.295 *    If full is set to false and mode is set to 2, it will print only the fields that contains a value. For example: 3h 295ms */ stock TimerFormat(hTimer, output[], maxlen, mode = 1, bool:full = false) {     new len;         if ( full || TimerDays(hTimer) )         len = formatex(output, maxlen, mode == 1 ? "%02d:" : "%dd ", TimerDays(hTimer));     if ( full || ( len && mode == 1 ) || TimerHours(hTimer) )         len += formatex(output[len], maxlen - len, mode == 1 ? "%02d:" : "%dh ", TimerHours(hTimer));     if ( full || ( len && mode == 1 ) || TimerMinutes(hTimer) )         len += formatex(output[len], maxlen - len, mode == 1 ? "%02d:" : "%dm ", TimerMinutes(hTimer));             if ( full || ( len && mode == 1 ) || TimerSeconds(hTimer) )         len += formatex(output[len], maxlen - len, mode == 1 ? "%02d." : "%ds ", TimerSeconds(hTimer));     if ( full || ! len || mode == 1 || TimerMilliseconds(hTimer) )         len += formatex(output[len], maxlen - len, mode == 1 ? "%03d" : "%dms", TimerMilliseconds(hTimer)); } public plugin_init() {     register_plugin("Test Plugin 2", "1.0", "[ --{[email protected] ]");     new cyc = 1000000     test(5, cyc, 1);     test(50, cyc, 1);     test(500, cyc, 1);     test(5000, cyc, 1);     test(5, cyc, 2);     test(50, cyc, 2);     test(500, cyc, 2);     test(5000, cyc, 2); } test(range, cycles, method) {     new test;     new hTimer;     if ( method == 1 ) {         hTimer = TimerStart();         for ( new i ; i < cycles ; i++ ) {             random_coord1(test, range);         }         TimerStop(hTimer);     }     else {         hTimer = TimerStart();         for ( new i ; i < cycles ; i++ ) {             random_coord2(test, range);         }         TimerStop(hTimer);     }     new output;     TimerFormat(hTimer, output, charsmax(output), 2);     server_print("Testing %dM cycles of method %d. Time: %s", cycles/1000000, method, output) } stock random_coord1(coord, range) {     new newCoord, tempCoord;     tempCoord = coord;     tempCoord = coord;     do {         newCoord = tempCoord + random_num(-range, range);         newCoord = tempCoord + random_num(-range, range);     }     while ( get_distance(newCoord, tempCoord) > range ) } stock random_coord2(Origin, range){     new Float:rand_coord     new Float:theta     new Float:r     new Float:rand             rand = random_float(0.0, 1.0);   //randomize the smaller radius     rand = random_float(0.0, 1.0);   //randomize the angle multiplication factor     r = range * rand     theta = rand * 6                 // i use 6 instead of 2*PI , don't judge me (dont really need extra accuracy)     rand_coord = r*floatcos(theta, radian)     rand_coord = r*floatsin(theta, radian)        Origin += rand_coord;     Origin += rand_coord; }``` Code: ```Testing 1M cycles of method 1. Time: 375ms Testing 1M cycles of method 1. Time: 406ms Testing 1M cycles of method 1. Time: 405ms Testing 1M cycles of method 1. Time: 403ms Testing 1M cycles of method 2. Time: 765ms Testing 1M cycles of method 2. Time: 765ms Testing 1M cycles of method 2. Time: 762ms Testing 1M cycles of method 2. Time: 784ms``` __________________ Last edited by Black Rose; 10-15-2020 at 14:58.  HamletEagle
AMX Mod X Plugin Approver
Join Date: Sep 2013
Location: Romania  10-16-2020 , 02:04   Re: Which method is more efficient? #5

Quote:
 Originally Posted by Natsheh PHP Code: ``` random_coord_within_region(Float:x, Float:y, radius=5.0, Float:random_coord){   random_coord = random_float(-radius, radius) + x;   random_coord = random_float(-radius, radius) + y;}  ```
This is generating points inside the rectangle R(x - radius, x + radius, y - radius, y + radius), not in a circle. Quote:
 Originally Posted by Black Rose Code: ```stock random_coord1(coord, range) {     new newCoord, tempCoord;     tempCoord = coord;     tempCoord = coord;     do {         newCoord = tempCoord + random_num(-range, range);         newCoord = tempCoord + random_num(-range, range);     }     while ( get_distance(newCoord, tempCoord) > range ) }``` I don't understand the second code so I'm not sure if it's correct. That itself should be a reason to chose the first code. But the first code is faster as well. Spoiler Code: ```#include /* Measures the actual time (even if the server is frozen due to working) for up to almost 25d. new hTimer = TimerStart(); // ... TimerStop(hTimer); */ #define TimerStart()            tickcount() #define TimerMid(%0)            ( tickcount() - %0 ) #define TimerStop(%0)         ( %0 = tickcount() - %0 ) #define TimerDays(%0)         ( %0 / 86400000 ) #define TimerHours(%0)      ( %0 % 86400000 / 3600000 ) #define TimerMinutes(%0)        ( %0 % 3600000 / 60000 ) #define TimerSeconds(%0)        ( %0 % 60000 / 1000 ) #define TimerMilliseconds(%0)   ( %0 % 1000 ) /* TimerFormat(hTimer, output[], maxlen, mode = 1, bool:full = 0) * Formats the result of a timer handle into a string. * * Parameters: * * hTimer *    Timer Handle * * output[] *    The output string * * maxlen *    Maximum size of the output string * * mode *    1: 00:00:00:00.000 *    2: 0d 0h 0m 0s 0ms * * bool:full *    If full is set to true it will print all fields, even those which contains no value. *    If full is set to false and mode is set to 1, it will print the first field that contains a value and everything after that point. For example: 03:00:00.295 *    If full is set to false and mode is set to 2, it will print only the fields that contains a value. For example: 3h 295ms */ stock TimerFormat(hTimer, output[], maxlen, mode = 1, bool:full = false) {     new len;         if ( full || TimerDays(hTimer) )         len = formatex(output, maxlen, mode == 1 ? "%02d:" : "%dd ", TimerDays(hTimer));     if ( full || ( len && mode == 1 ) || TimerHours(hTimer) )         len += formatex(output[len], maxlen - len, mode == 1 ? "%02d:" : "%dh ", TimerHours(hTimer));     if ( full || ( len && mode == 1 ) || TimerMinutes(hTimer) )         len += formatex(output[len], maxlen - len, mode == 1 ? "%02d:" : "%dm ", TimerMinutes(hTimer));             if ( full || ( len && mode == 1 ) || TimerSeconds(hTimer) )         len += formatex(output[len], maxlen - len, mode == 1 ? "%02d." : "%ds ", TimerSeconds(hTimer));     if ( full || ! len || mode == 1 || TimerMilliseconds(hTimer) )         len += formatex(output[len], maxlen - len, mode == 1 ? "%03d" : "%dms", TimerMilliseconds(hTimer)); } public plugin_init() {     register_plugin("Test Plugin 2", "1.0", "[ --{[email protected] ]");     new cyc = 1000000     test(5, cyc, 1);     test(50, cyc, 1);     test(500, cyc, 1);     test(5000, cyc, 1);     test(5, cyc, 2);     test(50, cyc, 2);     test(500, cyc, 2);     test(5000, cyc, 2); } test(range, cycles, method) {     new test;     new hTimer;     if ( method == 1 ) {         hTimer = TimerStart();         for ( new i ; i < cycles ; i++ ) {             random_coord1(test, range);         }         TimerStop(hTimer);     }     else {         hTimer = TimerStart();         for ( new i ; i < cycles ; i++ ) {             random_coord2(test, range);         }         TimerStop(hTimer);     }     new output;     TimerFormat(hTimer, output, charsmax(output), 2);     server_print("Testing %dM cycles of method %d. Time: %s", cycles/1000000, method, output) } stock random_coord1(coord, range) {     new newCoord, tempCoord;     tempCoord = coord;     tempCoord = coord;     do {         newCoord = tempCoord + random_num(-range, range);         newCoord = tempCoord + random_num(-range, range);     }     while ( get_distance(newCoord, tempCoord) > range ) } stock random_coord2(Origin, range){     new Float:rand_coord     new Float:theta     new Float:r     new Float:rand             rand = random_float(0.0, 1.0);   //randomize the smaller radius     rand = random_float(0.0, 1.0);   //randomize the angle multiplication factor     r = range * rand     theta = rand * 6                 // i use 6 instead of 2*PI , don't judge me (dont really need extra accuracy)     rand_coord = r*floatcos(theta, radian)     rand_coord = r*floatsin(theta, radian)        Origin += rand_coord;     Origin += rand_coord; }``` Code: ```Testing 1M cycles of method 1. Time: 375ms Testing 1M cycles of method 1. Time: 406ms Testing 1M cycles of method 1. Time: 405ms Testing 1M cycles of method 1. Time: 403ms Testing 1M cycles of method 2. Time: 765ms Testing 1M cycles of method 2. Time: 765ms Testing 1M cycles of method 2. Time: 762ms Testing 1M cycles of method 2. Time: 784ms```
The second code is actually very clever. To define a circle we need the center(which is the variable Origin) and a radius. We end up with circle C(Origin, Origin, r). Then by varying the radius, we can generate points inside the main circle, so ultimately we are generating points over the surface of the disk.
The only problem is these points will be specified in polar coordinates, we need to convert into cartesian coordinates which is what he is doing here(in order to have them fully defined in polar coordinates we need to pick a random theta angle in [0, 2pi))
PHP Code:
``` rand_coord = r*floatcos(theta, radian)rand_coord = r*floatsin(theta, radian)  ```
PHP Code:
``` x = r * cos(theta)y = r * sin(theta)  ```
This code is guaranteed to work and produce good results so I'd go with it. It is slower because of the usage of sin and cos functions, but if you REALLY need the last bit of speed you can build a table and cache the values of sin & cos for angles theta in [0, 2pi)

The first code appears to be faster in that particular test, but it is non deterministic. Technically, it may never converge to a point inside the circle.
__________________

Last edited by HamletEagle; 10-16-2020 at 03:06.  Siveroo
Junior Member
Join Date: Apr 2020  Today , 03:31   Re: Which method is more efficient? #6

Quote:
 Originally Posted by HamletEagle This is generating points inside the rectangle R(x - radius, x + radius, y - radius, y + radius), not in a circle. The second code is actually very clever. To define a circle we need the center(which is the variable Origin) and a radius. We end up with circle C(Origin, Origin, r). Then by varying the radius, we can generate points inside the main circle, so ultimately we are generating points over the surface of the disk. The only problem is these points will be specified in polar coordinates, we need to convert into cartesian coordinates which is what he is doing here(in order to have them fully defined in polar coordinates we need to pick a random theta angle in [0, 2pi)) PHP Code: ``` rand_coord = r*floatcos(theta, radian) rand_coord = r*floatsin(theta, radian)  ``` PHP Code: ``` x = r * cos(theta) y = r * sin(theta)  ``` This code is guaranteed to work and produce good results so I'd go with it. It is slower because of the usage of sin and cos functions, but if you REALLY need the last bit of speed you can build a table and cache the values of sin & cos for angles theta in [0, 2pi) The first code appears to be faster in that particular test, but it is non deterministic. Technically, it may never converge to a point inside the circle.
yup youre correct, the first code is simpler and easier to undestand, but it's just a bruteforce method, and as a people who likes math a lot, i try not to use it  , so i think i'll try to use the second code using some caching method and then see which one is faster.. however, im still going to use the faster one no matter the method.. thanks.

Last edited by Siveroo; Today at 03:46. Reason: there's more thing to say :)  HamletEagle
AMX Mod X Plugin Approver
Join Date: Sep 2013
Location: Romania  Today , 04:45   Re: Which method is more efficient? #7 With the first method, it is possible the algorithm will never converge or converge after a really long time(i.e all new generated points are inside the R\C area) which will end up being much slower than the second method. At the very least you should limit the max number of iterations to avoid (nearly) infinite loops. That's a very common practice when dealing with such algorithms. Something like this: PHP Code: ``` new maxIters = 500while(condition && maxIters-- > 0){    //do something}  ``` I should also mention that corectness is always more important than performance. No point in a fast yet flawed algorithm. __________________ Last edited by HamletEagle; Today at 04:52.  Siveroo
Junior Member
Join Date: Apr 2020  Today , 05:29   Re: Which method is more efficient? #8

Quote:
 Originally Posted by HamletEagle With the first method, it is possible the algorithm will never converge or converge after a really long time(i.e all new generated points are inside the R\C area) which will end up being much slower than the second method. At the very least you should limit the max number of iterations to avoid (nearly) infinite loops. That's a very common practice when dealing with such algorithms. Something like this: PHP Code: ``` new maxIters = 500while(condition && maxIters-- > 0){    //do something}  ``` I should also mention that corectness is always more important than performance. No point in a fast yet flawed algorithm.
yeah , dont worry im aware of that possibility.. and like i said i dont really like the first code even if the chance of it's not converging is really really stupid low. thanks for the response tho, really appreciate it!

EDIT : the chance of the first code doesnt converge after 10 attempts (in percent) maybe if i wanna use the first code, im going to limit the iteration like 10 times only, and if it still cant find generate the point inside the circle, just going to replace it with the origin , since the occurence of this event happening are somewhat still "random", although i still hate this method..

Last edited by Siveroo; Today at 05:51.  Today, 12:00 HamletEagle This message has been deleted by HamletEagle. fysiks
Veteran Member
Join Date: Sep 2007
Location: Flatland, USA  Today , 22:37   Re: Which method is more efficient? #9 If you're not running on a PC built in the 1970's then using sine and cosine won't add significant performance cost. __________________ Last edited by fysiks; Today at 22:38. Thread Tools Show Printable Version Email this Page Display Modes Linear Mode Switch to Hybrid Mode Switch to Threaded Mode Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is Off Forum Rules
 Forum Jump User Control Panel Private Messages Subscriptions Who's Online Search Forums Forums Home Server Discussion     Source Servers (SRCDS)     HL1 Servers (HLDS) AMX Mod X     News     Bug Reports     General     Off-Topic     Plugins         Suggestions / Requests         Approved Plugins         New Plugin Submissions         Unapproved/Old Plugins         Translation Request         High-Traffic Plugins             GunGame             UAIO (Ultimate All-In-One Plugin)             xREDIRECT             CSDM             AMX Super             RuneMod             Zombie Plague Mod             SuperHero Mod                 News                 Tech Support                 Scripting Help                 Off-Topic / General Chat                 Heroes                     Suggestions / Requests                     Approved Heroes                     New Submissions                     Unapproved/Old Heroes                         Module Heroes                     SuperHero Mod Stats - By 123                 (OLD) Bug Reports     Scripting         Scripting Help         Code Snippets/Tutorials         Module Coding     Donor Access SourceMod     News     General     Plugins         Plugins         Unapproved Plugins         Plugin/Gameplay Ideas and Requests         High-Traffic Plugins             SourceMod Anti-Cheat             Zombie:Reloaded             SourceBans / SourceBans++             VSH / Freak Fortress             Store             SM_Hosties             HLstatsX:CE     Scripting     Extensions     Snippets and Tutorials     Donor Access     Metamod: Source         Metamod:Source Plugins         Metamod:Source Questions         Coding MM:S Plugins & SM Extensions Hosted Stuff     Asherkin's Plugins         TFDodgeball         TF2Items         SteamTools     Bail's Plugins         CSDM         CS:S DM Off-Topic & Trash     Off-Topic     Trash

All times are GMT -4. The time now is 23:29.

 DMCA - Archive - Top