Strange recursion optimization by java -


i came across weird results when trying answer question: how improve performance of recursive method?

but don't need read post. i'll give relevant context here. might seem lengthy isn't complicated if read through once. hope interesting all. context,

syra(n) = { 1 if n=1;              n + syra(n/2) if n even; ,              n + syra(3n+1) if n odd           } 

and

syralen(n) = no. of steps calculate syra (n) 

e.g, syralen(1)=1, syralen(2)=2 since need go 2 steps. syra(10) = 10 + syra(5) = 15 + syra(16) = 31 + syra(8) = 39 + syra(4) = 43 + syra(2) = 45 + syra(1) = 46. syra(10) needed 7 steps. therefore syralen(10)=7

and finally,

lengths(n) = syralen(1)+syralen(2)+...+syralen(n) 

the question poster there trying calculate lengths(n)

my question recursive solution op has posted (which second snippet in question). i'll repost here:

public class syralengths{          int total=1;         public int syralength(long n) {             if (n < 1)                 throw new illegalargumentexception();             if (n == 1) {                 int temp=total;                 total=1;                 return temp;             }             else if (n % 2 == 0) {                 total++;                 return syralength(n / 2);             }             else {                 total++;                 return syralength(n * 3 + 1);             }         }          public int lengths(int n){             if(n<1){                 throw new illegalargumentexception();             }             int total=0;             for(int i=1;i<=n;i++){                 total+=syralength(i);             }              return total;         }          public static void main(string[] args){             system.out.println(new syralengths().lengths(5000000));         }        } 

surely unusual (and not recommended) way of doing recursively, calculate right thing, have verified that. tried write more usual recursive version of same:

public class syraslow {      public long lengths(int n) {         long total = 0;         (int = 1; <= n; ++i) {             total += syralen(i);         }         return total;     }      private long syralen(int i) {         if (i == 1)             return 1;         return 1 + ((i % 2 == 0) ? syralen(i / 2) : syralen(i * 3 + 1));     } 

now here's weird part - tried test performance of both above versions like:

public static void main(string[] args){             long t1=0,t2=0;             int test_val=50000;              t1 = system.currenttimemillis();             system.out.println(new syralengths().lengths(test_val));             t2 = system.currenttimemillis();             system.out.println("syralengths time taken: " + (t2-t1));              t1 = system.currenttimemillis();             system.out.println(new syraslow().lengths(test_val));             t2 = system.currenttimemillis();             system.out.println("syraslow time taken: " + (t2-t1));         } 

for test_val=50000, output is:

5075114 syralengths time taken: 44 5075114 syraslow time taken: 31 

as expected (i guess) plain recursion better. when go 1 step further , use test_val=500000, output is:

62634795 syralengths time taken: 378 exception in thread "main" java.lang.stackoverflowerror     @ syraslow.syralen(syraslow.java:15)     @ syraslow.syralen(syraslow.java:15)     @ syraslow.syralen(syraslow.java:15) 

why it? kind of optimization being done java here syralengths version doesn't hit stackoverflow (it works @ test_val=5000000)? i tried using accumulator-based recursive version in case jvm doing tail-call optimization:

private long syralenacc(int i, long acc) {         if (i == 1) return acc;     if(i%2==0) {         return syralenacc(i/2,acc+1);     }     return syralenacc(i * 3 + 1, acc+1);     } 

but still got same result (thus there no tail-call optimization here). then, what's happening here?

p.s: please edit better title if can think of any.

with original version, tail recursion optimization possible (within jit). dunno whether occurred or not, though. it's possible original more efficient heap [er, mean stack] use. (or there may functional difference not obvious on cursory examination.)


Comments

Popular posts from this blog

java - Play! framework 2.0: How to display multiple image? -

gmail - Is there any documentation for read-only access to the Google Contacts API? -

php - Controller/JToolBar not working in Joomla 2.5 -