Get reverse of an equation - JavaScript












25















Let's say I have this formula, for example:






function getExperience(level) {
let a = 0;
for (let x = 1; x < level; x += 1) {
a += Math.floor(x + (200 * (2 ** (x / 3))));
}

return Math.floor(a / 4);
}


for (var i = 1; i < 100; i++) {
console.log(`Level ${i}: ${getExperience(i)}`);
}





To get the experience needed for level 50, you'd do: getExperience(50).



But, how would you reverse that and get the LEVEL needed for experience? So, getLevel(20010272) would output 50.










share|improve this question























  • You can test getExperience in a loop until you get the same result (level).

    – SphynxTech
    Jan 30 at 6:51











  • It seems there's a typo. getExperience(50) is 20012272, not 20010272. So I guess getLevel(20010272) should return 49, not 50.

    – Eric Duminil
    Jan 30 at 9:45











  • This is an infinite series, but you could simplify and get an inverse function.

    – Scuba Steve
    Jan 31 at 1:18











  • See also How can I calculate current level from total XP, when each level requires proportionally more XP? on Game Development.

    – Ilmari Karonen
    Jan 31 at 2:49
















25















Let's say I have this formula, for example:






function getExperience(level) {
let a = 0;
for (let x = 1; x < level; x += 1) {
a += Math.floor(x + (200 * (2 ** (x / 3))));
}

return Math.floor(a / 4);
}


for (var i = 1; i < 100; i++) {
console.log(`Level ${i}: ${getExperience(i)}`);
}





To get the experience needed for level 50, you'd do: getExperience(50).



But, how would you reverse that and get the LEVEL needed for experience? So, getLevel(20010272) would output 50.










share|improve this question























  • You can test getExperience in a loop until you get the same result (level).

    – SphynxTech
    Jan 30 at 6:51











  • It seems there's a typo. getExperience(50) is 20012272, not 20010272. So I guess getLevel(20010272) should return 49, not 50.

    – Eric Duminil
    Jan 30 at 9:45











  • This is an infinite series, but you could simplify and get an inverse function.

    – Scuba Steve
    Jan 31 at 1:18











  • See also How can I calculate current level from total XP, when each level requires proportionally more XP? on Game Development.

    – Ilmari Karonen
    Jan 31 at 2:49














25












25








25


3






Let's say I have this formula, for example:






function getExperience(level) {
let a = 0;
for (let x = 1; x < level; x += 1) {
a += Math.floor(x + (200 * (2 ** (x / 3))));
}

return Math.floor(a / 4);
}


for (var i = 1; i < 100; i++) {
console.log(`Level ${i}: ${getExperience(i)}`);
}





To get the experience needed for level 50, you'd do: getExperience(50).



But, how would you reverse that and get the LEVEL needed for experience? So, getLevel(20010272) would output 50.










share|improve this question














Let's say I have this formula, for example:






function getExperience(level) {
let a = 0;
for (let x = 1; x < level; x += 1) {
a += Math.floor(x + (200 * (2 ** (x / 3))));
}

return Math.floor(a / 4);
}


for (var i = 1; i < 100; i++) {
console.log(`Level ${i}: ${getExperience(i)}`);
}





To get the experience needed for level 50, you'd do: getExperience(50).



But, how would you reverse that and get the LEVEL needed for experience? So, getLevel(20010272) would output 50.






function getExperience(level) {
let a = 0;
for (let x = 1; x < level; x += 1) {
a += Math.floor(x + (200 * (2 ** (x / 3))));
}

return Math.floor(a / 4);
}


for (var i = 1; i < 100; i++) {
console.log(`Level ${i}: ${getExperience(i)}`);
}





function getExperience(level) {
let a = 0;
for (let x = 1; x < level; x += 1) {
a += Math.floor(x + (200 * (2 ** (x / 3))));
}

return Math.floor(a / 4);
}


for (var i = 1; i < 100; i++) {
console.log(`Level ${i}: ${getExperience(i)}`);
}






javascript math






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 30 at 6:47









Green MtnGreen Mtn

15816




15816













  • You can test getExperience in a loop until you get the same result (level).

    – SphynxTech
    Jan 30 at 6:51











  • It seems there's a typo. getExperience(50) is 20012272, not 20010272. So I guess getLevel(20010272) should return 49, not 50.

    – Eric Duminil
    Jan 30 at 9:45











  • This is an infinite series, but you could simplify and get an inverse function.

    – Scuba Steve
    Jan 31 at 1:18











  • See also How can I calculate current level from total XP, when each level requires proportionally more XP? on Game Development.

    – Ilmari Karonen
    Jan 31 at 2:49



















  • You can test getExperience in a loop until you get the same result (level).

    – SphynxTech
    Jan 30 at 6:51











  • It seems there's a typo. getExperience(50) is 20012272, not 20010272. So I guess getLevel(20010272) should return 49, not 50.

    – Eric Duminil
    Jan 30 at 9:45











  • This is an infinite series, but you could simplify and get an inverse function.

    – Scuba Steve
    Jan 31 at 1:18











  • See also How can I calculate current level from total XP, when each level requires proportionally more XP? on Game Development.

    – Ilmari Karonen
    Jan 31 at 2:49

















You can test getExperience in a loop until you get the same result (level).

– SphynxTech
Jan 30 at 6:51





You can test getExperience in a loop until you get the same result (level).

– SphynxTech
Jan 30 at 6:51













It seems there's a typo. getExperience(50) is 20012272, not 20010272. So I guess getLevel(20010272) should return 49, not 50.

– Eric Duminil
Jan 30 at 9:45





It seems there's a typo. getExperience(50) is 20012272, not 20010272. So I guess getLevel(20010272) should return 49, not 50.

– Eric Duminil
Jan 30 at 9:45













This is an infinite series, but you could simplify and get an inverse function.

– Scuba Steve
Jan 31 at 1:18





This is an infinite series, but you could simplify and get an inverse function.

– Scuba Steve
Jan 31 at 1:18













See also How can I calculate current level from total XP, when each level requires proportionally more XP? on Game Development.

– Ilmari Karonen
Jan 31 at 2:49





See also How can I calculate current level from total XP, when each level requires proportionally more XP? on Game Development.

– Ilmari Karonen
Jan 31 at 2:49












5 Answers
5






active

oldest

votes


















42














Short answer



You can use 4.328085 * Math.log(0.00519842 * xp + 1.259921045) as a very good approximation of the corresponding level.



If you need an exact value, you could iterate over all levels until you find the desired range, as in this answer.



Long answer



Slightly modified function



I don't think it's possible to find an exact, closed-form expression for the inverse of this function. It should be possible if you modify getExperience(level) a bit, though.




  • First, you can notice that x grows much slower than 2 ** (x / 3).

  • Then, Math.floor doesn't have much influence over large numbers.


So let's remove them! Here's the slightly modified function:



function getExperienceEstimate(level) {
let a = 0;
for (let x = 1; x < level; x += 1) {
a += 200 * (2 ** (x / 3));
}
return a / 4;
}


The advantage of this method is that it's now a geometric series, so it's possible to calculate the sum directly, without any loop:



function getExperienceEstimate(level) {
let a = 50;
let r = 2 ** (1 / 3);
return a * (r**level - r) / (r - 1);
};


getExperienceEstimate(50) returns 20011971.993575357, which is only 0.0015% smaller than getExperience(50).



Inverse function



According to Wolfram Alpha, here's the inverse function of getExperienceEstimate:



function getLevelEstimate(xp){
let a = 50;
let r = 2 ** (1 / 3);
return Math.log(xp * (r - 1) / a + r) / Math.log(r);
};


With some minor precision loss, you can simplify it further:



function getLevelEstimate(xp){
return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
};


It's only an estimate, but it works pretty well and doesn't require any loop!



Test



For 20012272 XP, the approximate inverse function returns 50.00006263463371, which should be a good starting point if you want to find the exact result.






function getExperience(level) {
let a = 0;
for (let x = 1; x < level; x += 1) {
a += Math.floor(x + (200 * (2 ** (x / 3))));
}
return Math.floor(a / 4);
}

function getLevelEstimate(xp){
return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
};

for (var i = 1; i < 100; i++) {
console.log(`Level ${i} (XP = ${getExperience(i)}). Estimated level : ${getLevelEstimate(getExperience(i))}`);
}








share|improve this answer





















  • 4





    This is the solution I would go for. In my game, I made sure I could directly inverse my level formula by using the same exponent to both log and pow. I would recommend OP do that if at all possible to minimize the worry about approximation and instead to make it an exact match.

    – Seiyria
    Jan 30 at 15:36











  • You could start with this approximation, then loop over a few nearby numbers to find the right one.

    – Barmar
    Jan 30 at 21:38











  • And from your results, it looks like simply doing Math.round(getLevelEstimate(experience)) would work.

    – Barmar
    Jan 30 at 21:39






  • 1





    I also tried to find the inverse of the experience formula but failed. +1.

    – Salman A
    Jan 31 at 7:01











  • @Barmar: The interesting information is for which experience getLevelEstimate switches to the next level. If you call Math.round, you throw away this information. With a perfect getLevelEstimate, Math.floor should return the correct level.

    – Eric Duminil
    Jan 31 at 11:15



















12














A brute-force (but inelegant) solution would be to just call getExperience for levels until you reach a level that requires more experience than the passed exp:






function getLevel(exp) {
if (exp === 0) return 0;
let level = 0;
let calcExp = 0;
while (exp > calcExp) {
calcExp = getExperience(level);
if (calcExp > exp) break;
level++;
}
return level - 1;
}

console.log(getLevel(20012272)); // experience required for 50 on the dot
console.log(getLevel(20012270));
console.log(getLevel(20012274));
console.log(getLevel(0));

function getExperience(level) {
let a = 0;
for (let x = 1; x < level; x += 1) {
a += Math.floor(x + (200 * (2 ** (x / 3))));
}

return Math.floor(a / 4);
}








share|improve this answer





















  • 1





    Just wondering if we can minimize the iteration by setting level to a relatively nearer value

    – Rajesh
    Jan 30 at 7:00











  • A simple solution that gets the job done. Why did I think of this. Argh. Thank you.

    – Green Mtn
    Jan 30 at 7:08






  • 6





    You could, of course, pre-compute all the values and have them in a lookup table. I doubt the XP requirement or levels would change all the time, so dynamically computing them every single time seems like an overkill.

    – VLAZ
    Jan 30 at 9:10






  • 4





    If you knew minimum/maximum levels as well, you could do a pseudo-binary search (i.e. if you knew there are exactly 100 levels, you see if your experience is less than or greater than level 50's, then 25/75 depending on that, then 12/38/62/88, etc). Or somewhere between those steps (bisect until you have 3 options, then check all those).

    – Delioth
    Jan 30 at 20:54











  • Yay! I got the populist badge thanks to your accepted answer. Thanks ;)

    – Eric Duminil
    Jan 31 at 7:59



















12














You can use a binary search algorithm to avoid to loop over all possibilities.



Here is an example that I have adapted to your case.



You first need to create an array to map all your level => experience, this action should be done only ONCE, then you never have to do it again.



As you can see in my example, even with 1000 levels, you never have to iterate more than 9 times whatever level you are trying to find.






// You first have to create an array with all your levels.
// This has to be done only ONCE because it's an expensive one!
const list = ;
for (let i = 1; i <= 1000; i++) {
list[i] = getExperience(i);
}

function getExperience(level) {
let a = 0;
for (let x = 1; x < level; x += 1) {
a += Math.floor(x + (200 * (2 ** (x / 3))));
}

return Math.floor(a / 4);
}

function getLevel(value) {
// initial values for start, middle and end
let start = 0
let stop = list.length - 1
let middle = Math.floor((start + stop) / 2)
let iterations = 0;

// While the middle is not what we're looking for and the list does not have a single item.
while (list[middle] !== value && start < stop) {
iterations++;
if (value < list[middle]) {
stop = middle - 1
} else {
start = middle + 1
}

// Recalculate middle on every iteration.
middle = Math.floor((start + stop) / 2)
}

console.log(`${value} is Level ${middle} (Result found after ${iterations} iterations)`);
return middle;
}

// Then you can search your level according to the experience
getLevel(0);
getLevel(72);
getLevel(20010272);
getLevel(getExperience(50));
getLevel(33578608987644589722);








share|improve this answer





















  • 1





    You can improve creation of the list by looping Math.floor(x + (200 * (2 ** (x / 3)))) from 1 to 1000 and storing the a values, then looping again to get Math.floor(a / 4)

    – JollyJoker
    Jan 30 at 8:46











  • @JollyJoker Hmm possible, can you edit my answer with your suggestion?

    – Armel
    Jan 30 at 8:50











  • Try it online! Edit it in if you want to; it's not as readable as I'd like

    – JollyJoker
    Jan 30 at 9:04











  • @EricDuminil Absolutely, it was an index problem with the initialization of the list, I fixed it, thank you.

    – Armel
    Jan 30 at 9:58






  • 4





    You dont have to build the list of all experiences.

    – Salman A
    Jan 30 at 10:32



















2














You can use binary search to locate level value faster - in 7 steps max.



(while I doubt that gain is significant for length 100 list)






share|improve this answer































    1














    The binary search idea could be used as follows. Note that the following assumes that there are maximum 100 levels. You can change it to 1000, 10000 or 100000 if necessary.






    function getExperience(level) {
    let a = 0;
    for (let x = 1; x < level; x += 1) {
    a += Math.floor(x + (200 * (2 ** (x / 3))));
    }
    return Math.floor(a / 4);
    }

    function getLevel(exp) {
    let min = 1,
    max = 100;
    while (min <= max) {
    let mid = Math.floor((min + max) / 2),
    expm = getExperience(mid),
    expn = getExperience(mid + 1);
    if (expm <= exp && exp < expn) {
    return mid;
    }
    if (expm < exp) {
    min = mid + 1;
    } else {
    max = mid - 1;
    }
    }
    return null;
    }

    console.log(getLevel(getExperience(17)));
    console.log(getLevel(getExperience(17) - 1));
    console.log(getLevel(getExperience(100)));
    console.log(getLevel(getExperience(100) - 1));








    share|improve this answer


























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54434757%2fget-reverse-of-an-equation-javascript%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      42














      Short answer



      You can use 4.328085 * Math.log(0.00519842 * xp + 1.259921045) as a very good approximation of the corresponding level.



      If you need an exact value, you could iterate over all levels until you find the desired range, as in this answer.



      Long answer



      Slightly modified function



      I don't think it's possible to find an exact, closed-form expression for the inverse of this function. It should be possible if you modify getExperience(level) a bit, though.




      • First, you can notice that x grows much slower than 2 ** (x / 3).

      • Then, Math.floor doesn't have much influence over large numbers.


      So let's remove them! Here's the slightly modified function:



      function getExperienceEstimate(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += 200 * (2 ** (x / 3));
      }
      return a / 4;
      }


      The advantage of this method is that it's now a geometric series, so it's possible to calculate the sum directly, without any loop:



      function getExperienceEstimate(level) {
      let a = 50;
      let r = 2 ** (1 / 3);
      return a * (r**level - r) / (r - 1);
      };


      getExperienceEstimate(50) returns 20011971.993575357, which is only 0.0015% smaller than getExperience(50).



      Inverse function



      According to Wolfram Alpha, here's the inverse function of getExperienceEstimate:



      function getLevelEstimate(xp){
      let a = 50;
      let r = 2 ** (1 / 3);
      return Math.log(xp * (r - 1) / a + r) / Math.log(r);
      };


      With some minor precision loss, you can simplify it further:



      function getLevelEstimate(xp){
      return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
      };


      It's only an estimate, but it works pretty well and doesn't require any loop!



      Test



      For 20012272 XP, the approximate inverse function returns 50.00006263463371, which should be a good starting point if you want to find the exact result.






      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }
      return Math.floor(a / 4);
      }

      function getLevelEstimate(xp){
      return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
      };

      for (var i = 1; i < 100; i++) {
      console.log(`Level ${i} (XP = ${getExperience(i)}). Estimated level : ${getLevelEstimate(getExperience(i))}`);
      }








      share|improve this answer





















      • 4





        This is the solution I would go for. In my game, I made sure I could directly inverse my level formula by using the same exponent to both log and pow. I would recommend OP do that if at all possible to minimize the worry about approximation and instead to make it an exact match.

        – Seiyria
        Jan 30 at 15:36











      • You could start with this approximation, then loop over a few nearby numbers to find the right one.

        – Barmar
        Jan 30 at 21:38











      • And from your results, it looks like simply doing Math.round(getLevelEstimate(experience)) would work.

        – Barmar
        Jan 30 at 21:39






      • 1





        I also tried to find the inverse of the experience formula but failed. +1.

        – Salman A
        Jan 31 at 7:01











      • @Barmar: The interesting information is for which experience getLevelEstimate switches to the next level. If you call Math.round, you throw away this information. With a perfect getLevelEstimate, Math.floor should return the correct level.

        – Eric Duminil
        Jan 31 at 11:15
















      42














      Short answer



      You can use 4.328085 * Math.log(0.00519842 * xp + 1.259921045) as a very good approximation of the corresponding level.



      If you need an exact value, you could iterate over all levels until you find the desired range, as in this answer.



      Long answer



      Slightly modified function



      I don't think it's possible to find an exact, closed-form expression for the inverse of this function. It should be possible if you modify getExperience(level) a bit, though.




      • First, you can notice that x grows much slower than 2 ** (x / 3).

      • Then, Math.floor doesn't have much influence over large numbers.


      So let's remove them! Here's the slightly modified function:



      function getExperienceEstimate(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += 200 * (2 ** (x / 3));
      }
      return a / 4;
      }


      The advantage of this method is that it's now a geometric series, so it's possible to calculate the sum directly, without any loop:



      function getExperienceEstimate(level) {
      let a = 50;
      let r = 2 ** (1 / 3);
      return a * (r**level - r) / (r - 1);
      };


      getExperienceEstimate(50) returns 20011971.993575357, which is only 0.0015% smaller than getExperience(50).



      Inverse function



      According to Wolfram Alpha, here's the inverse function of getExperienceEstimate:



      function getLevelEstimate(xp){
      let a = 50;
      let r = 2 ** (1 / 3);
      return Math.log(xp * (r - 1) / a + r) / Math.log(r);
      };


      With some minor precision loss, you can simplify it further:



      function getLevelEstimate(xp){
      return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
      };


      It's only an estimate, but it works pretty well and doesn't require any loop!



      Test



      For 20012272 XP, the approximate inverse function returns 50.00006263463371, which should be a good starting point if you want to find the exact result.






      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }
      return Math.floor(a / 4);
      }

      function getLevelEstimate(xp){
      return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
      };

      for (var i = 1; i < 100; i++) {
      console.log(`Level ${i} (XP = ${getExperience(i)}). Estimated level : ${getLevelEstimate(getExperience(i))}`);
      }








      share|improve this answer





















      • 4





        This is the solution I would go for. In my game, I made sure I could directly inverse my level formula by using the same exponent to both log and pow. I would recommend OP do that if at all possible to minimize the worry about approximation and instead to make it an exact match.

        – Seiyria
        Jan 30 at 15:36











      • You could start with this approximation, then loop over a few nearby numbers to find the right one.

        – Barmar
        Jan 30 at 21:38











      • And from your results, it looks like simply doing Math.round(getLevelEstimate(experience)) would work.

        – Barmar
        Jan 30 at 21:39






      • 1





        I also tried to find the inverse of the experience formula but failed. +1.

        – Salman A
        Jan 31 at 7:01











      • @Barmar: The interesting information is for which experience getLevelEstimate switches to the next level. If you call Math.round, you throw away this information. With a perfect getLevelEstimate, Math.floor should return the correct level.

        – Eric Duminil
        Jan 31 at 11:15














      42












      42








      42







      Short answer



      You can use 4.328085 * Math.log(0.00519842 * xp + 1.259921045) as a very good approximation of the corresponding level.



      If you need an exact value, you could iterate over all levels until you find the desired range, as in this answer.



      Long answer



      Slightly modified function



      I don't think it's possible to find an exact, closed-form expression for the inverse of this function. It should be possible if you modify getExperience(level) a bit, though.




      • First, you can notice that x grows much slower than 2 ** (x / 3).

      • Then, Math.floor doesn't have much influence over large numbers.


      So let's remove them! Here's the slightly modified function:



      function getExperienceEstimate(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += 200 * (2 ** (x / 3));
      }
      return a / 4;
      }


      The advantage of this method is that it's now a geometric series, so it's possible to calculate the sum directly, without any loop:



      function getExperienceEstimate(level) {
      let a = 50;
      let r = 2 ** (1 / 3);
      return a * (r**level - r) / (r - 1);
      };


      getExperienceEstimate(50) returns 20011971.993575357, which is only 0.0015% smaller than getExperience(50).



      Inverse function



      According to Wolfram Alpha, here's the inverse function of getExperienceEstimate:



      function getLevelEstimate(xp){
      let a = 50;
      let r = 2 ** (1 / 3);
      return Math.log(xp * (r - 1) / a + r) / Math.log(r);
      };


      With some minor precision loss, you can simplify it further:



      function getLevelEstimate(xp){
      return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
      };


      It's only an estimate, but it works pretty well and doesn't require any loop!



      Test



      For 20012272 XP, the approximate inverse function returns 50.00006263463371, which should be a good starting point if you want to find the exact result.






      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }
      return Math.floor(a / 4);
      }

      function getLevelEstimate(xp){
      return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
      };

      for (var i = 1; i < 100; i++) {
      console.log(`Level ${i} (XP = ${getExperience(i)}). Estimated level : ${getLevelEstimate(getExperience(i))}`);
      }








      share|improve this answer















      Short answer



      You can use 4.328085 * Math.log(0.00519842 * xp + 1.259921045) as a very good approximation of the corresponding level.



      If you need an exact value, you could iterate over all levels until you find the desired range, as in this answer.



      Long answer



      Slightly modified function



      I don't think it's possible to find an exact, closed-form expression for the inverse of this function. It should be possible if you modify getExperience(level) a bit, though.




      • First, you can notice that x grows much slower than 2 ** (x / 3).

      • Then, Math.floor doesn't have much influence over large numbers.


      So let's remove them! Here's the slightly modified function:



      function getExperienceEstimate(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += 200 * (2 ** (x / 3));
      }
      return a / 4;
      }


      The advantage of this method is that it's now a geometric series, so it's possible to calculate the sum directly, without any loop:



      function getExperienceEstimate(level) {
      let a = 50;
      let r = 2 ** (1 / 3);
      return a * (r**level - r) / (r - 1);
      };


      getExperienceEstimate(50) returns 20011971.993575357, which is only 0.0015% smaller than getExperience(50).



      Inverse function



      According to Wolfram Alpha, here's the inverse function of getExperienceEstimate:



      function getLevelEstimate(xp){
      let a = 50;
      let r = 2 ** (1 / 3);
      return Math.log(xp * (r - 1) / a + r) / Math.log(r);
      };


      With some minor precision loss, you can simplify it further:



      function getLevelEstimate(xp){
      return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
      };


      It's only an estimate, but it works pretty well and doesn't require any loop!



      Test



      For 20012272 XP, the approximate inverse function returns 50.00006263463371, which should be a good starting point if you want to find the exact result.






      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }
      return Math.floor(a / 4);
      }

      function getLevelEstimate(xp){
      return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
      };

      for (var i = 1; i < 100; i++) {
      console.log(`Level ${i} (XP = ${getExperience(i)}). Estimated level : ${getLevelEstimate(getExperience(i))}`);
      }








      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }
      return Math.floor(a / 4);
      }

      function getLevelEstimate(xp){
      return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
      };

      for (var i = 1; i < 100; i++) {
      console.log(`Level ${i} (XP = ${getExperience(i)}). Estimated level : ${getLevelEstimate(getExperience(i))}`);
      }





      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }
      return Math.floor(a / 4);
      }

      function getLevelEstimate(xp){
      return 4.328085 * Math.log(0.00519842 * xp + 1.259921045)
      };

      for (var i = 1; i < 100; i++) {
      console.log(`Level ${i} (XP = ${getExperience(i)}). Estimated level : ${getLevelEstimate(getExperience(i))}`);
      }






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 31 at 21:46

























      answered Jan 30 at 10:55









      Eric DuminilEric Duminil

      40.6k63371




      40.6k63371








      • 4





        This is the solution I would go for. In my game, I made sure I could directly inverse my level formula by using the same exponent to both log and pow. I would recommend OP do that if at all possible to minimize the worry about approximation and instead to make it an exact match.

        – Seiyria
        Jan 30 at 15:36











      • You could start with this approximation, then loop over a few nearby numbers to find the right one.

        – Barmar
        Jan 30 at 21:38











      • And from your results, it looks like simply doing Math.round(getLevelEstimate(experience)) would work.

        – Barmar
        Jan 30 at 21:39






      • 1





        I also tried to find the inverse of the experience formula but failed. +1.

        – Salman A
        Jan 31 at 7:01











      • @Barmar: The interesting information is for which experience getLevelEstimate switches to the next level. If you call Math.round, you throw away this information. With a perfect getLevelEstimate, Math.floor should return the correct level.

        – Eric Duminil
        Jan 31 at 11:15














      • 4





        This is the solution I would go for. In my game, I made sure I could directly inverse my level formula by using the same exponent to both log and pow. I would recommend OP do that if at all possible to minimize the worry about approximation and instead to make it an exact match.

        – Seiyria
        Jan 30 at 15:36











      • You could start with this approximation, then loop over a few nearby numbers to find the right one.

        – Barmar
        Jan 30 at 21:38











      • And from your results, it looks like simply doing Math.round(getLevelEstimate(experience)) would work.

        – Barmar
        Jan 30 at 21:39






      • 1





        I also tried to find the inverse of the experience formula but failed. +1.

        – Salman A
        Jan 31 at 7:01











      • @Barmar: The interesting information is for which experience getLevelEstimate switches to the next level. If you call Math.round, you throw away this information. With a perfect getLevelEstimate, Math.floor should return the correct level.

        – Eric Duminil
        Jan 31 at 11:15








      4




      4





      This is the solution I would go for. In my game, I made sure I could directly inverse my level formula by using the same exponent to both log and pow. I would recommend OP do that if at all possible to minimize the worry about approximation and instead to make it an exact match.

      – Seiyria
      Jan 30 at 15:36





      This is the solution I would go for. In my game, I made sure I could directly inverse my level formula by using the same exponent to both log and pow. I would recommend OP do that if at all possible to minimize the worry about approximation and instead to make it an exact match.

      – Seiyria
      Jan 30 at 15:36













      You could start with this approximation, then loop over a few nearby numbers to find the right one.

      – Barmar
      Jan 30 at 21:38





      You could start with this approximation, then loop over a few nearby numbers to find the right one.

      – Barmar
      Jan 30 at 21:38













      And from your results, it looks like simply doing Math.round(getLevelEstimate(experience)) would work.

      – Barmar
      Jan 30 at 21:39





      And from your results, it looks like simply doing Math.round(getLevelEstimate(experience)) would work.

      – Barmar
      Jan 30 at 21:39




      1




      1





      I also tried to find the inverse of the experience formula but failed. +1.

      – Salman A
      Jan 31 at 7:01





      I also tried to find the inverse of the experience formula but failed. +1.

      – Salman A
      Jan 31 at 7:01













      @Barmar: The interesting information is for which experience getLevelEstimate switches to the next level. If you call Math.round, you throw away this information. With a perfect getLevelEstimate, Math.floor should return the correct level.

      – Eric Duminil
      Jan 31 at 11:15





      @Barmar: The interesting information is for which experience getLevelEstimate switches to the next level. If you call Math.round, you throw away this information. With a perfect getLevelEstimate, Math.floor should return the correct level.

      – Eric Duminil
      Jan 31 at 11:15













      12














      A brute-force (but inelegant) solution would be to just call getExperience for levels until you reach a level that requires more experience than the passed exp:






      function getLevel(exp) {
      if (exp === 0) return 0;
      let level = 0;
      let calcExp = 0;
      while (exp > calcExp) {
      calcExp = getExperience(level);
      if (calcExp > exp) break;
      level++;
      }
      return level - 1;
      }

      console.log(getLevel(20012272)); // experience required for 50 on the dot
      console.log(getLevel(20012270));
      console.log(getLevel(20012274));
      console.log(getLevel(0));

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }








      share|improve this answer





















      • 1





        Just wondering if we can minimize the iteration by setting level to a relatively nearer value

        – Rajesh
        Jan 30 at 7:00











      • A simple solution that gets the job done. Why did I think of this. Argh. Thank you.

        – Green Mtn
        Jan 30 at 7:08






      • 6





        You could, of course, pre-compute all the values and have them in a lookup table. I doubt the XP requirement or levels would change all the time, so dynamically computing them every single time seems like an overkill.

        – VLAZ
        Jan 30 at 9:10






      • 4





        If you knew minimum/maximum levels as well, you could do a pseudo-binary search (i.e. if you knew there are exactly 100 levels, you see if your experience is less than or greater than level 50's, then 25/75 depending on that, then 12/38/62/88, etc). Or somewhere between those steps (bisect until you have 3 options, then check all those).

        – Delioth
        Jan 30 at 20:54











      • Yay! I got the populist badge thanks to your accepted answer. Thanks ;)

        – Eric Duminil
        Jan 31 at 7:59
















      12














      A brute-force (but inelegant) solution would be to just call getExperience for levels until you reach a level that requires more experience than the passed exp:






      function getLevel(exp) {
      if (exp === 0) return 0;
      let level = 0;
      let calcExp = 0;
      while (exp > calcExp) {
      calcExp = getExperience(level);
      if (calcExp > exp) break;
      level++;
      }
      return level - 1;
      }

      console.log(getLevel(20012272)); // experience required for 50 on the dot
      console.log(getLevel(20012270));
      console.log(getLevel(20012274));
      console.log(getLevel(0));

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }








      share|improve this answer





















      • 1





        Just wondering if we can minimize the iteration by setting level to a relatively nearer value

        – Rajesh
        Jan 30 at 7:00











      • A simple solution that gets the job done. Why did I think of this. Argh. Thank you.

        – Green Mtn
        Jan 30 at 7:08






      • 6





        You could, of course, pre-compute all the values and have them in a lookup table. I doubt the XP requirement or levels would change all the time, so dynamically computing them every single time seems like an overkill.

        – VLAZ
        Jan 30 at 9:10






      • 4





        If you knew minimum/maximum levels as well, you could do a pseudo-binary search (i.e. if you knew there are exactly 100 levels, you see if your experience is less than or greater than level 50's, then 25/75 depending on that, then 12/38/62/88, etc). Or somewhere between those steps (bisect until you have 3 options, then check all those).

        – Delioth
        Jan 30 at 20:54











      • Yay! I got the populist badge thanks to your accepted answer. Thanks ;)

        – Eric Duminil
        Jan 31 at 7:59














      12












      12








      12







      A brute-force (but inelegant) solution would be to just call getExperience for levels until you reach a level that requires more experience than the passed exp:






      function getLevel(exp) {
      if (exp === 0) return 0;
      let level = 0;
      let calcExp = 0;
      while (exp > calcExp) {
      calcExp = getExperience(level);
      if (calcExp > exp) break;
      level++;
      }
      return level - 1;
      }

      console.log(getLevel(20012272)); // experience required for 50 on the dot
      console.log(getLevel(20012270));
      console.log(getLevel(20012274));
      console.log(getLevel(0));

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }








      share|improve this answer















      A brute-force (but inelegant) solution would be to just call getExperience for levels until you reach a level that requires more experience than the passed exp:






      function getLevel(exp) {
      if (exp === 0) return 0;
      let level = 0;
      let calcExp = 0;
      while (exp > calcExp) {
      calcExp = getExperience(level);
      if (calcExp > exp) break;
      level++;
      }
      return level - 1;
      }

      console.log(getLevel(20012272)); // experience required for 50 on the dot
      console.log(getLevel(20012270));
      console.log(getLevel(20012274));
      console.log(getLevel(0));

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }








      function getLevel(exp) {
      if (exp === 0) return 0;
      let level = 0;
      let calcExp = 0;
      while (exp > calcExp) {
      calcExp = getExperience(level);
      if (calcExp > exp) break;
      level++;
      }
      return level - 1;
      }

      console.log(getLevel(20012272)); // experience required for 50 on the dot
      console.log(getLevel(20012270));
      console.log(getLevel(20012274));
      console.log(getLevel(0));

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }





      function getLevel(exp) {
      if (exp === 0) return 0;
      let level = 0;
      let calcExp = 0;
      while (exp > calcExp) {
      calcExp = getExperience(level);
      if (calcExp > exp) break;
      level++;
      }
      return level - 1;
      }

      console.log(getLevel(20012272)); // experience required for 50 on the dot
      console.log(getLevel(20012270));
      console.log(getLevel(20012274));
      console.log(getLevel(0));

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 30 at 9:51

























      answered Jan 30 at 6:55









      CertainPerformanceCertainPerformance

      97.3k165887




      97.3k165887








      • 1





        Just wondering if we can minimize the iteration by setting level to a relatively nearer value

        – Rajesh
        Jan 30 at 7:00











      • A simple solution that gets the job done. Why did I think of this. Argh. Thank you.

        – Green Mtn
        Jan 30 at 7:08






      • 6





        You could, of course, pre-compute all the values and have them in a lookup table. I doubt the XP requirement or levels would change all the time, so dynamically computing them every single time seems like an overkill.

        – VLAZ
        Jan 30 at 9:10






      • 4





        If you knew minimum/maximum levels as well, you could do a pseudo-binary search (i.e. if you knew there are exactly 100 levels, you see if your experience is less than or greater than level 50's, then 25/75 depending on that, then 12/38/62/88, etc). Or somewhere between those steps (bisect until you have 3 options, then check all those).

        – Delioth
        Jan 30 at 20:54











      • Yay! I got the populist badge thanks to your accepted answer. Thanks ;)

        – Eric Duminil
        Jan 31 at 7:59














      • 1





        Just wondering if we can minimize the iteration by setting level to a relatively nearer value

        – Rajesh
        Jan 30 at 7:00











      • A simple solution that gets the job done. Why did I think of this. Argh. Thank you.

        – Green Mtn
        Jan 30 at 7:08






      • 6





        You could, of course, pre-compute all the values and have them in a lookup table. I doubt the XP requirement or levels would change all the time, so dynamically computing them every single time seems like an overkill.

        – VLAZ
        Jan 30 at 9:10






      • 4





        If you knew minimum/maximum levels as well, you could do a pseudo-binary search (i.e. if you knew there are exactly 100 levels, you see if your experience is less than or greater than level 50's, then 25/75 depending on that, then 12/38/62/88, etc). Or somewhere between those steps (bisect until you have 3 options, then check all those).

        – Delioth
        Jan 30 at 20:54











      • Yay! I got the populist badge thanks to your accepted answer. Thanks ;)

        – Eric Duminil
        Jan 31 at 7:59








      1




      1





      Just wondering if we can minimize the iteration by setting level to a relatively nearer value

      – Rajesh
      Jan 30 at 7:00





      Just wondering if we can minimize the iteration by setting level to a relatively nearer value

      – Rajesh
      Jan 30 at 7:00













      A simple solution that gets the job done. Why did I think of this. Argh. Thank you.

      – Green Mtn
      Jan 30 at 7:08





      A simple solution that gets the job done. Why did I think of this. Argh. Thank you.

      – Green Mtn
      Jan 30 at 7:08




      6




      6





      You could, of course, pre-compute all the values and have them in a lookup table. I doubt the XP requirement or levels would change all the time, so dynamically computing them every single time seems like an overkill.

      – VLAZ
      Jan 30 at 9:10





      You could, of course, pre-compute all the values and have them in a lookup table. I doubt the XP requirement or levels would change all the time, so dynamically computing them every single time seems like an overkill.

      – VLAZ
      Jan 30 at 9:10




      4




      4





      If you knew minimum/maximum levels as well, you could do a pseudo-binary search (i.e. if you knew there are exactly 100 levels, you see if your experience is less than or greater than level 50's, then 25/75 depending on that, then 12/38/62/88, etc). Or somewhere between those steps (bisect until you have 3 options, then check all those).

      – Delioth
      Jan 30 at 20:54





      If you knew minimum/maximum levels as well, you could do a pseudo-binary search (i.e. if you knew there are exactly 100 levels, you see if your experience is less than or greater than level 50's, then 25/75 depending on that, then 12/38/62/88, etc). Or somewhere between those steps (bisect until you have 3 options, then check all those).

      – Delioth
      Jan 30 at 20:54













      Yay! I got the populist badge thanks to your accepted answer. Thanks ;)

      – Eric Duminil
      Jan 31 at 7:59





      Yay! I got the populist badge thanks to your accepted answer. Thanks ;)

      – Eric Duminil
      Jan 31 at 7:59











      12














      You can use a binary search algorithm to avoid to loop over all possibilities.



      Here is an example that I have adapted to your case.



      You first need to create an array to map all your level => experience, this action should be done only ONCE, then you never have to do it again.



      As you can see in my example, even with 1000 levels, you never have to iterate more than 9 times whatever level you are trying to find.






      // You first have to create an array with all your levels.
      // This has to be done only ONCE because it's an expensive one!
      const list = ;
      for (let i = 1; i <= 1000; i++) {
      list[i] = getExperience(i);
      }

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }

      function getLevel(value) {
      // initial values for start, middle and end
      let start = 0
      let stop = list.length - 1
      let middle = Math.floor((start + stop) / 2)
      let iterations = 0;

      // While the middle is not what we're looking for and the list does not have a single item.
      while (list[middle] !== value && start < stop) {
      iterations++;
      if (value < list[middle]) {
      stop = middle - 1
      } else {
      start = middle + 1
      }

      // Recalculate middle on every iteration.
      middle = Math.floor((start + stop) / 2)
      }

      console.log(`${value} is Level ${middle} (Result found after ${iterations} iterations)`);
      return middle;
      }

      // Then you can search your level according to the experience
      getLevel(0);
      getLevel(72);
      getLevel(20010272);
      getLevel(getExperience(50));
      getLevel(33578608987644589722);








      share|improve this answer





















      • 1





        You can improve creation of the list by looping Math.floor(x + (200 * (2 ** (x / 3)))) from 1 to 1000 and storing the a values, then looping again to get Math.floor(a / 4)

        – JollyJoker
        Jan 30 at 8:46











      • @JollyJoker Hmm possible, can you edit my answer with your suggestion?

        – Armel
        Jan 30 at 8:50











      • Try it online! Edit it in if you want to; it's not as readable as I'd like

        – JollyJoker
        Jan 30 at 9:04











      • @EricDuminil Absolutely, it was an index problem with the initialization of the list, I fixed it, thank you.

        – Armel
        Jan 30 at 9:58






      • 4





        You dont have to build the list of all experiences.

        – Salman A
        Jan 30 at 10:32
















      12














      You can use a binary search algorithm to avoid to loop over all possibilities.



      Here is an example that I have adapted to your case.



      You first need to create an array to map all your level => experience, this action should be done only ONCE, then you never have to do it again.



      As you can see in my example, even with 1000 levels, you never have to iterate more than 9 times whatever level you are trying to find.






      // You first have to create an array with all your levels.
      // This has to be done only ONCE because it's an expensive one!
      const list = ;
      for (let i = 1; i <= 1000; i++) {
      list[i] = getExperience(i);
      }

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }

      function getLevel(value) {
      // initial values for start, middle and end
      let start = 0
      let stop = list.length - 1
      let middle = Math.floor((start + stop) / 2)
      let iterations = 0;

      // While the middle is not what we're looking for and the list does not have a single item.
      while (list[middle] !== value && start < stop) {
      iterations++;
      if (value < list[middle]) {
      stop = middle - 1
      } else {
      start = middle + 1
      }

      // Recalculate middle on every iteration.
      middle = Math.floor((start + stop) / 2)
      }

      console.log(`${value} is Level ${middle} (Result found after ${iterations} iterations)`);
      return middle;
      }

      // Then you can search your level according to the experience
      getLevel(0);
      getLevel(72);
      getLevel(20010272);
      getLevel(getExperience(50));
      getLevel(33578608987644589722);








      share|improve this answer





















      • 1





        You can improve creation of the list by looping Math.floor(x + (200 * (2 ** (x / 3)))) from 1 to 1000 and storing the a values, then looping again to get Math.floor(a / 4)

        – JollyJoker
        Jan 30 at 8:46











      • @JollyJoker Hmm possible, can you edit my answer with your suggestion?

        – Armel
        Jan 30 at 8:50











      • Try it online! Edit it in if you want to; it's not as readable as I'd like

        – JollyJoker
        Jan 30 at 9:04











      • @EricDuminil Absolutely, it was an index problem with the initialization of the list, I fixed it, thank you.

        – Armel
        Jan 30 at 9:58






      • 4





        You dont have to build the list of all experiences.

        – Salman A
        Jan 30 at 10:32














      12












      12








      12







      You can use a binary search algorithm to avoid to loop over all possibilities.



      Here is an example that I have adapted to your case.



      You first need to create an array to map all your level => experience, this action should be done only ONCE, then you never have to do it again.



      As you can see in my example, even with 1000 levels, you never have to iterate more than 9 times whatever level you are trying to find.






      // You first have to create an array with all your levels.
      // This has to be done only ONCE because it's an expensive one!
      const list = ;
      for (let i = 1; i <= 1000; i++) {
      list[i] = getExperience(i);
      }

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }

      function getLevel(value) {
      // initial values for start, middle and end
      let start = 0
      let stop = list.length - 1
      let middle = Math.floor((start + stop) / 2)
      let iterations = 0;

      // While the middle is not what we're looking for and the list does not have a single item.
      while (list[middle] !== value && start < stop) {
      iterations++;
      if (value < list[middle]) {
      stop = middle - 1
      } else {
      start = middle + 1
      }

      // Recalculate middle on every iteration.
      middle = Math.floor((start + stop) / 2)
      }

      console.log(`${value} is Level ${middle} (Result found after ${iterations} iterations)`);
      return middle;
      }

      // Then you can search your level according to the experience
      getLevel(0);
      getLevel(72);
      getLevel(20010272);
      getLevel(getExperience(50));
      getLevel(33578608987644589722);








      share|improve this answer















      You can use a binary search algorithm to avoid to loop over all possibilities.



      Here is an example that I have adapted to your case.



      You first need to create an array to map all your level => experience, this action should be done only ONCE, then you never have to do it again.



      As you can see in my example, even with 1000 levels, you never have to iterate more than 9 times whatever level you are trying to find.






      // You first have to create an array with all your levels.
      // This has to be done only ONCE because it's an expensive one!
      const list = ;
      for (let i = 1; i <= 1000; i++) {
      list[i] = getExperience(i);
      }

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }

      function getLevel(value) {
      // initial values for start, middle and end
      let start = 0
      let stop = list.length - 1
      let middle = Math.floor((start + stop) / 2)
      let iterations = 0;

      // While the middle is not what we're looking for and the list does not have a single item.
      while (list[middle] !== value && start < stop) {
      iterations++;
      if (value < list[middle]) {
      stop = middle - 1
      } else {
      start = middle + 1
      }

      // Recalculate middle on every iteration.
      middle = Math.floor((start + stop) / 2)
      }

      console.log(`${value} is Level ${middle} (Result found after ${iterations} iterations)`);
      return middle;
      }

      // Then you can search your level according to the experience
      getLevel(0);
      getLevel(72);
      getLevel(20010272);
      getLevel(getExperience(50));
      getLevel(33578608987644589722);








      // You first have to create an array with all your levels.
      // This has to be done only ONCE because it's an expensive one!
      const list = ;
      for (let i = 1; i <= 1000; i++) {
      list[i] = getExperience(i);
      }

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }

      function getLevel(value) {
      // initial values for start, middle and end
      let start = 0
      let stop = list.length - 1
      let middle = Math.floor((start + stop) / 2)
      let iterations = 0;

      // While the middle is not what we're looking for and the list does not have a single item.
      while (list[middle] !== value && start < stop) {
      iterations++;
      if (value < list[middle]) {
      stop = middle - 1
      } else {
      start = middle + 1
      }

      // Recalculate middle on every iteration.
      middle = Math.floor((start + stop) / 2)
      }

      console.log(`${value} is Level ${middle} (Result found after ${iterations} iterations)`);
      return middle;
      }

      // Then you can search your level according to the experience
      getLevel(0);
      getLevel(72);
      getLevel(20010272);
      getLevel(getExperience(50));
      getLevel(33578608987644589722);





      // You first have to create an array with all your levels.
      // This has to be done only ONCE because it's an expensive one!
      const list = ;
      for (let i = 1; i <= 1000; i++) {
      list[i] = getExperience(i);
      }

      function getExperience(level) {
      let a = 0;
      for (let x = 1; x < level; x += 1) {
      a += Math.floor(x + (200 * (2 ** (x / 3))));
      }

      return Math.floor(a / 4);
      }

      function getLevel(value) {
      // initial values for start, middle and end
      let start = 0
      let stop = list.length - 1
      let middle = Math.floor((start + stop) / 2)
      let iterations = 0;

      // While the middle is not what we're looking for and the list does not have a single item.
      while (list[middle] !== value && start < stop) {
      iterations++;
      if (value < list[middle]) {
      stop = middle - 1
      } else {
      start = middle + 1
      }

      // Recalculate middle on every iteration.
      middle = Math.floor((start + stop) / 2)
      }

      console.log(`${value} is Level ${middle} (Result found after ${iterations} iterations)`);
      return middle;
      }

      // Then you can search your level according to the experience
      getLevel(0);
      getLevel(72);
      getLevel(20010272);
      getLevel(getExperience(50));
      getLevel(33578608987644589722);






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 30 at 17:23









      double-beep

      3,08141432




      3,08141432










      answered Jan 30 at 7:20









      ArmelArmel

      1,2041020




      1,2041020








      • 1





        You can improve creation of the list by looping Math.floor(x + (200 * (2 ** (x / 3)))) from 1 to 1000 and storing the a values, then looping again to get Math.floor(a / 4)

        – JollyJoker
        Jan 30 at 8:46











      • @JollyJoker Hmm possible, can you edit my answer with your suggestion?

        – Armel
        Jan 30 at 8:50











      • Try it online! Edit it in if you want to; it's not as readable as I'd like

        – JollyJoker
        Jan 30 at 9:04











      • @EricDuminil Absolutely, it was an index problem with the initialization of the list, I fixed it, thank you.

        – Armel
        Jan 30 at 9:58






      • 4





        You dont have to build the list of all experiences.

        – Salman A
        Jan 30 at 10:32














      • 1





        You can improve creation of the list by looping Math.floor(x + (200 * (2 ** (x / 3)))) from 1 to 1000 and storing the a values, then looping again to get Math.floor(a / 4)

        – JollyJoker
        Jan 30 at 8:46











      • @JollyJoker Hmm possible, can you edit my answer with your suggestion?

        – Armel
        Jan 30 at 8:50











      • Try it online! Edit it in if you want to; it's not as readable as I'd like

        – JollyJoker
        Jan 30 at 9:04











      • @EricDuminil Absolutely, it was an index problem with the initialization of the list, I fixed it, thank you.

        – Armel
        Jan 30 at 9:58






      • 4





        You dont have to build the list of all experiences.

        – Salman A
        Jan 30 at 10:32








      1




      1





      You can improve creation of the list by looping Math.floor(x + (200 * (2 ** (x / 3)))) from 1 to 1000 and storing the a values, then looping again to get Math.floor(a / 4)

      – JollyJoker
      Jan 30 at 8:46





      You can improve creation of the list by looping Math.floor(x + (200 * (2 ** (x / 3)))) from 1 to 1000 and storing the a values, then looping again to get Math.floor(a / 4)

      – JollyJoker
      Jan 30 at 8:46













      @JollyJoker Hmm possible, can you edit my answer with your suggestion?

      – Armel
      Jan 30 at 8:50





      @JollyJoker Hmm possible, can you edit my answer with your suggestion?

      – Armel
      Jan 30 at 8:50













      Try it online! Edit it in if you want to; it's not as readable as I'd like

      – JollyJoker
      Jan 30 at 9:04





      Try it online! Edit it in if you want to; it's not as readable as I'd like

      – JollyJoker
      Jan 30 at 9:04













      @EricDuminil Absolutely, it was an index problem with the initialization of the list, I fixed it, thank you.

      – Armel
      Jan 30 at 9:58





      @EricDuminil Absolutely, it was an index problem with the initialization of the list, I fixed it, thank you.

      – Armel
      Jan 30 at 9:58




      4




      4





      You dont have to build the list of all experiences.

      – Salman A
      Jan 30 at 10:32





      You dont have to build the list of all experiences.

      – Salman A
      Jan 30 at 10:32











      2














      You can use binary search to locate level value faster - in 7 steps max.



      (while I doubt that gain is significant for length 100 list)






      share|improve this answer




























        2














        You can use binary search to locate level value faster - in 7 steps max.



        (while I doubt that gain is significant for length 100 list)






        share|improve this answer


























          2












          2








          2







          You can use binary search to locate level value faster - in 7 steps max.



          (while I doubt that gain is significant for length 100 list)






          share|improve this answer













          You can use binary search to locate level value faster - in 7 steps max.



          (while I doubt that gain is significant for length 100 list)







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jan 30 at 7:00









          MBoMBo

          50.2k23052




          50.2k23052























              1














              The binary search idea could be used as follows. Note that the following assumes that there are maximum 100 levels. You can change it to 1000, 10000 or 100000 if necessary.






              function getExperience(level) {
              let a = 0;
              for (let x = 1; x < level; x += 1) {
              a += Math.floor(x + (200 * (2 ** (x / 3))));
              }
              return Math.floor(a / 4);
              }

              function getLevel(exp) {
              let min = 1,
              max = 100;
              while (min <= max) {
              let mid = Math.floor((min + max) / 2),
              expm = getExperience(mid),
              expn = getExperience(mid + 1);
              if (expm <= exp && exp < expn) {
              return mid;
              }
              if (expm < exp) {
              min = mid + 1;
              } else {
              max = mid - 1;
              }
              }
              return null;
              }

              console.log(getLevel(getExperience(17)));
              console.log(getLevel(getExperience(17) - 1));
              console.log(getLevel(getExperience(100)));
              console.log(getLevel(getExperience(100) - 1));








              share|improve this answer






























                1














                The binary search idea could be used as follows. Note that the following assumes that there are maximum 100 levels. You can change it to 1000, 10000 or 100000 if necessary.






                function getExperience(level) {
                let a = 0;
                for (let x = 1; x < level; x += 1) {
                a += Math.floor(x + (200 * (2 ** (x / 3))));
                }
                return Math.floor(a / 4);
                }

                function getLevel(exp) {
                let min = 1,
                max = 100;
                while (min <= max) {
                let mid = Math.floor((min + max) / 2),
                expm = getExperience(mid),
                expn = getExperience(mid + 1);
                if (expm <= exp && exp < expn) {
                return mid;
                }
                if (expm < exp) {
                min = mid + 1;
                } else {
                max = mid - 1;
                }
                }
                return null;
                }

                console.log(getLevel(getExperience(17)));
                console.log(getLevel(getExperience(17) - 1));
                console.log(getLevel(getExperience(100)));
                console.log(getLevel(getExperience(100) - 1));








                share|improve this answer




























                  1












                  1








                  1







                  The binary search idea could be used as follows. Note that the following assumes that there are maximum 100 levels. You can change it to 1000, 10000 or 100000 if necessary.






                  function getExperience(level) {
                  let a = 0;
                  for (let x = 1; x < level; x += 1) {
                  a += Math.floor(x + (200 * (2 ** (x / 3))));
                  }
                  return Math.floor(a / 4);
                  }

                  function getLevel(exp) {
                  let min = 1,
                  max = 100;
                  while (min <= max) {
                  let mid = Math.floor((min + max) / 2),
                  expm = getExperience(mid),
                  expn = getExperience(mid + 1);
                  if (expm <= exp && exp < expn) {
                  return mid;
                  }
                  if (expm < exp) {
                  min = mid + 1;
                  } else {
                  max = mid - 1;
                  }
                  }
                  return null;
                  }

                  console.log(getLevel(getExperience(17)));
                  console.log(getLevel(getExperience(17) - 1));
                  console.log(getLevel(getExperience(100)));
                  console.log(getLevel(getExperience(100) - 1));








                  share|improve this answer















                  The binary search idea could be used as follows. Note that the following assumes that there are maximum 100 levels. You can change it to 1000, 10000 or 100000 if necessary.






                  function getExperience(level) {
                  let a = 0;
                  for (let x = 1; x < level; x += 1) {
                  a += Math.floor(x + (200 * (2 ** (x / 3))));
                  }
                  return Math.floor(a / 4);
                  }

                  function getLevel(exp) {
                  let min = 1,
                  max = 100;
                  while (min <= max) {
                  let mid = Math.floor((min + max) / 2),
                  expm = getExperience(mid),
                  expn = getExperience(mid + 1);
                  if (expm <= exp && exp < expn) {
                  return mid;
                  }
                  if (expm < exp) {
                  min = mid + 1;
                  } else {
                  max = mid - 1;
                  }
                  }
                  return null;
                  }

                  console.log(getLevel(getExperience(17)));
                  console.log(getLevel(getExperience(17) - 1));
                  console.log(getLevel(getExperience(100)));
                  console.log(getLevel(getExperience(100) - 1));








                  function getExperience(level) {
                  let a = 0;
                  for (let x = 1; x < level; x += 1) {
                  a += Math.floor(x + (200 * (2 ** (x / 3))));
                  }
                  return Math.floor(a / 4);
                  }

                  function getLevel(exp) {
                  let min = 1,
                  max = 100;
                  while (min <= max) {
                  let mid = Math.floor((min + max) / 2),
                  expm = getExperience(mid),
                  expn = getExperience(mid + 1);
                  if (expm <= exp && exp < expn) {
                  return mid;
                  }
                  if (expm < exp) {
                  min = mid + 1;
                  } else {
                  max = mid - 1;
                  }
                  }
                  return null;
                  }

                  console.log(getLevel(getExperience(17)));
                  console.log(getLevel(getExperience(17) - 1));
                  console.log(getLevel(getExperience(100)));
                  console.log(getLevel(getExperience(100) - 1));





                  function getExperience(level) {
                  let a = 0;
                  for (let x = 1; x < level; x += 1) {
                  a += Math.floor(x + (200 * (2 ** (x / 3))));
                  }
                  return Math.floor(a / 4);
                  }

                  function getLevel(exp) {
                  let min = 1,
                  max = 100;
                  while (min <= max) {
                  let mid = Math.floor((min + max) / 2),
                  expm = getExperience(mid),
                  expn = getExperience(mid + 1);
                  if (expm <= exp && exp < expn) {
                  return mid;
                  }
                  if (expm < exp) {
                  min = mid + 1;
                  } else {
                  max = mid - 1;
                  }
                  }
                  return null;
                  }

                  console.log(getLevel(getExperience(17)));
                  console.log(getLevel(getExperience(17) - 1));
                  console.log(getLevel(getExperience(100)));
                  console.log(getLevel(getExperience(100) - 1));






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Jan 30 at 10:16

























                  answered Jan 30 at 9:15









                  Salman ASalman A

                  185k67345441




                  185k67345441






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54434757%2fget-reverse-of-an-equation-javascript%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      MongoDB - Not Authorized To Execute Command

                      How to fix TextFormField cause rebuild widget in Flutter

                      in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith