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
.
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.
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.
x
grows much slower than 2 ** (x / 3)
.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)
.
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!
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))}`); }
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With