Get reverse of an equation - JavaScript
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
.
javascript math
add a comment |
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
.
javascript math
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)
is20012272
, not20010272
. So I guessgetLevel(20010272)
should return49
, not50
.
– 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
add a comment |
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
.
javascript math
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
javascript math
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)
is20012272
, not20010272
. So I guessgetLevel(20010272)
should return49
, not50
.
– 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
add a comment |
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)
is20012272
, not20010272
. So I guessgetLevel(20010272)
should return49
, not50
.
– 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
add a comment |
5 Answers
5
active
oldest
votes
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 than2 ** (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))}`);
}
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 doingMath.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 experiencegetLevelEstimate
switches to the next level. If you callMath.round
, you throw away this information. With a perfectgetLevelEstimate
,Math.floor
should return the correct level.
– Eric Duminil
Jan 31 at 11:15
|
show 2 more comments
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);
}
1
Just wondering if we can minimize the iteration by settinglevel
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
add a comment |
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);
1
You can improve creation of the list by loopingMath.floor(x + (200 * (2 ** (x / 3))))
from 1 to 1000 and storing thea
values, then looping again to getMath.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 anindex
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
|
show 2 more comments
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)
add a comment |
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));
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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 than2 ** (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))}`);
}
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 doingMath.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 experiencegetLevelEstimate
switches to the next level. If you callMath.round
, you throw away this information. With a perfectgetLevelEstimate
,Math.floor
should return the correct level.
– Eric Duminil
Jan 31 at 11:15
|
show 2 more comments
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 than2 ** (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))}`);
}
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 doingMath.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 experiencegetLevelEstimate
switches to the next level. If you callMath.round
, you throw away this information. With a perfectgetLevelEstimate
,Math.floor
should return the correct level.
– Eric Duminil
Jan 31 at 11:15
|
show 2 more comments
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 than2 ** (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))}`);
}
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 than2 ** (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))}`);
}
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 doingMath.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 experiencegetLevelEstimate
switches to the next level. If you callMath.round
, you throw away this information. With a perfectgetLevelEstimate
,Math.floor
should return the correct level.
– Eric Duminil
Jan 31 at 11:15
|
show 2 more comments
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 doingMath.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 experiencegetLevelEstimate
switches to the next level. If you callMath.round
, you throw away this information. With a perfectgetLevelEstimate
,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
|
show 2 more comments
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);
}
1
Just wondering if we can minimize the iteration by settinglevel
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
add a comment |
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);
}
1
Just wondering if we can minimize the iteration by settinglevel
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
add a comment |
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);
}
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);
}
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 settinglevel
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
add a comment |
1
Just wondering if we can minimize the iteration by settinglevel
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
add a comment |
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);
1
You can improve creation of the list by loopingMath.floor(x + (200 * (2 ** (x / 3))))
from 1 to 1000 and storing thea
values, then looping again to getMath.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 anindex
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
|
show 2 more comments
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);
1
You can improve creation of the list by loopingMath.floor(x + (200 * (2 ** (x / 3))))
from 1 to 1000 and storing thea
values, then looping again to getMath.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 anindex
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
|
show 2 more comments
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 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);
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 loopingMath.floor(x + (200 * (2 ** (x / 3))))
from 1 to 1000 and storing thea
values, then looping again to getMath.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 anindex
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
|
show 2 more comments
1
You can improve creation of the list by loopingMath.floor(x + (200 * (2 ** (x / 3))))
from 1 to 1000 and storing thea
values, then looping again to getMath.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 anindex
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
|
show 2 more comments
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)
add a comment |
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)
add a comment |
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)
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)
answered Jan 30 at 7:00
MBoMBo
50.2k23052
50.2k23052
add a comment |
add a comment |
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));
add a comment |
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));
add a comment |
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));
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));
edited Jan 30 at 10:16
answered Jan 30 at 9:15
Salman ASalman A
185k67345441
185k67345441
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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)
is20012272
, not20010272
. So I guessgetLevel(20010272)
should return49
, not50
.– 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