Good day all,
I am trying to create a simple small bet calculator with the following line of codes:
function betCalculator(moneyLine) {
var odds;
var betAmount = 500;
if (moneyLine > 0) {
odds = (moneyLine / 100) + 1;
} else {
odds = (100 / moneyLine) + 1;
}
return parseFloat((odds * betAmount).toFixed(2));
}
console.log(betCalculator(130)); // Result / Expected = 1150.00
But if I change the Money Line to negative, say -130, as shown below:
function betCalculator(moneyLine) {
var odds;
var betAmount = 500;
if (moneyLine > 0) {
odds = (moneyLine / 100) + 1;
} else {
odds = (100 / moneyLine) + 1;
}
return parseFloat((odds * betAmount).toFixed(2));
}
console.log(betCalculator(-130)); // Result I am getting = 115.38 // Expected = 884.62
What I am trying to do is:
if (moneyLine > 0) {
odds = (moneyLine / 100) + 1;
But
if (moneyLine < 0) {
odds = (100 / moneyLine) + 1;
Any help would be appreciated.
Regards,
ZeManel
For the calculation for the negative moneyLine, you want to change the sign, or use the absolute value, when you move it to the denominator.
If you change odds = (100 / moneyLine) + 1; in your else condition to odds = (100 / Math.abs(moneyLine)) + 1;, then you will get your expected answer.
Related
I'm trying to create a calculator that when you input your points, and the total amount of points in the class you receive a lot of information about it, I currently have working the letter grade, percentage, and the amount of points that you need to get to the next grade up.
Ex. 95/100
A 95%
Points Needed = 5
I want to do the same thing with Points needed but opposite. So with the same example it would be
Points Lost = 5
I currently have the script for my current Points Needed if it helps, but I really can't figure out the equation for this, luckily not necessary for a school project, just for a solo project so I can learn how to code.
Here is the code for the Points Needed
var pointsNeeded = totalGrade.value - grade.value;
if (gradePercentage > 100) {
pointsNeeded = pointsNeeded * -1;
document.getElementById("pointsNeeded").innerHTML = "You can lose " + pointsNeeded + " point(s) and still have 100%";
}
else {
document.getElementById("pointsNeeded").innerHTML = pointsNeeded;
}
}
else if (gradePercentage < 89, gradePercentage > 79) {
var pointsNeeded = Math.round(10 * ((totalGrade.value * 0.9) -
grade.value)) / 10;
document.getElementById("pointsNeeded").innerHTML = pointsNeeded;
}
else if (gradePercentage < 79, gradePercentage > 69) {
var pointsNeeded = Math.round(10 * ((totalGrade.value * 0.8) -
grade.value)) / 10;
document.getElementById("pointsNeeded").innerHTML = pointsNeeded;
}
else if (gradePercentage < 69, gradePercentage > 59) {
var pointsNeeded = Math.round(10 * ((totalGrade.value * 0.7) -
grade.value)) / 10;
document.getElementById("pointsNeeded").innerHTML = pointsNeeded;
}
else if (gradePercentage < 59) {
var pointsNeeded = Math.round(10 * ((totalGrade.value * 0.6) -
grade.value)) / 10;
document.getElementById("pointsNeeded").innerHTML = pointsNeeded;
}
gradePercentage being the actual percentage, totalGrade being the full grade, and grade being the grade you have.
Also these are the grade values,
var gradeLetter = "A"
document.getElementById("result").innerHTML = gradeLetter + " " + result + "%";
}
if (gradePercentage > 79.9, gradePercentage < 90) {
var gradeLetter = "B"
document.getElementById("result").innerHTML = gradeLetter + " " + result + "%";
}
if (gradePercentage > 69.9, gradePercentage < 80) {
var gradeLetter = "C"
document.getElementById("result").innerHTML = gradeLetter + " " + result + "%";
}
if (gradePercentage > 59.9, gradePercentage < 70) {
var gradeLetter = "D"
document.getElementById("result").innerHTML = gradeLetter + " " + result + "%";
}
if (gradePercentage < 59.9) {
var gradeLetter = "F"
document.getElementById("result").innerHTML = gradeLetter + " " + result + "%";
}
This code is pretty self-explanatory:
let startingPoints = 952.3 // How many points you got on the test
let maxPoints = 1049 // Max possible points you could have gotten
// Your grade (0-100%):
let gradePercentage = 100 * startingPoints / maxPoints; // E.g. 90.7816968541468
// How much less you'd need (as a percentage) to get the next lowest grade:
let extraPercentage = ( gradePercentage % 10 ) + 0.01; // E.g. 0.7916968541468015
// Your new grade (as a percentage) if you bumped it down:
let newGrade = gradePercentage - extraPercentage; // E.g. 89.99
// How many points you'd have to reduce your score by to bump it down to the next lowest
let extraPoints = ( extraPercentage / 100 * maxPoints ) // E.g. 8.304899999999947
// What your score would be if you bumped it down to the next level:
let newExtraPoints = startingPoints - extraPoints; // E.g. 943.9951
console.log( `Your grade is ${gradePercentage}% (${startingPoints} points out of a possible ${maxPoints}). If you subtract ${extraPercentage}% (or ${extraPoints} points), your grade will be ${newGrade}% (${newExtraPoints} points)` );
The only trickiness is that we're adding 0.01, which technically could be 0.001, or 0.0001, or...well, we have to add something to drop below the limit, and with no set "right" amount, I'm choosing 0.01 because it works out nicely.
Example output:
Your grade is 90.7816968541468% (952.3 points out of a possible 1049).
If you subtract 0.7916968541468015% (or 8.304899999999947 points),
your grade will be 89.99% (943.9951 points)
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.
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))}`);
}
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);
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);
}
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)
This is how I generate 6 different numbers:
window.random_row = Math.floor(Math.random() * (len_board - 1)) + 1;
window.random_column = Math.floor(Math.random() * (len_board - 1)) + 1;
window.random_row2 = Math.floor(Math.random() * ((len_board-1) - 1)) + 1;
window.random_column2 = Math.floor(Math.random() * ((len_board-1) - 1)) + 1;
window.random_row3 = Math.floor(Math.random() * ((len_board+1) - 1)) + 1;
window.random_column3 = Math.floor(Math.random() * ((len_board+1) - 1)) + 1;
However, I don't want the rows/columns to be the same number, e.g random_row == random_column is allowed, but I don't want random_row == random_row2. I was thinking of using an if/else statement. Something along the lines of: if (random_row == random_row2) then generate a new random_row2 but it came to my mind that the number could be the same again so I guess that would not be the right way to go about it. Does anyone have an idea about how to solve this issue?
I saw a good answer in https://stackoverflow.com/a/2380113/5108174
Adapting to your question:
function generate(qt, len_board) {
var arr = [];
while(arr.length < qt) {
var randomnumber = Math.floor(Math.random() * (len_board - 1)) + 1;
if(arr.indexOf(randomnumber) > -1) continue;
arr.push(randomnumber);
}
return arr;
}
var rows=generate(3,len_board);
var columns=generate(3,len_board);
window.random_row = rows[0];
window.random_column = columns[0];
window.random_row2 = rows[1];
window.random_column2 = columns[1];
window.random_row3 = rows[2];
window.random_column3 = columns[2];
Create an array of numbers from 1 .. len-board
shuffle it (sort with Math.random() < 0.5 sort function)
take the first 6.
Think of it as like shuffling a deck of cards, that you cannot pull the same card twice.
All "unique".
What about trying with a while cycle?
while(random2 == random1 || random2 == random3)
{
random2= math.....;
}
var current = 12000;
var june = 14600;
var may = 11200;
I want percent change with respect to 'current' month parameter. The output should be in percent and it can add or subtract w.r.t. the current month. How to do this?
Note that if one of your values is 0 you will get either -100% or Infinity%.
This solves that problem:
function percIncrease(a, b) {
let percent;
if(b !== 0) {
if(a !== 0) {
percent = (b - a) / a * 100;
} else {
percent = b * 100;
}
} else {
percent = - a * 100;
}
return Math.floor(percent);
}
Its simple maths:
var res=(current-june)/current*100.0;
var percentchange = (june - current) / current * 100.0;
If your answer is a negative number then this is a percentage increase else decrease.
It isn't an easy task to handle specials cases, increase or decrease, rounding, over 100%, etc.
function calcPc(n1,n2){
return (((n2 - n1) / n1 * 100).toLocaleString('fullwide', {maximumFractionDigits:3}) + "%");
}
console.log(
" May: " , calcPc(11200,12000) ,
"\nJune:" , calcPc(14600,12000)
)
I'm working on the classic "making change" problem, which is highly documented in plenty of other languages, but there's not much out there for it in Javascript. So far, I have this:
var total = $('#total').val();
var coins = [];
function makeChange(total, coins) {
var remainder = 0;
if (total % 0.25 < total) {
coins[3] = parseInt(total / 0.25);
remainder = total % 0.25;
total = remainder;
}
if (total % 0.10 < total) {
coins[2] = parseInt(total / 0.10);
remainder = total % 0.10;
total = remainder;
}
if (total % 0.05 < total) {
coins[1] = parseInt(total / 0.05);
remainder = total % 0.05;
total = remainder;
}
coins[0] = parseInt(total / 0.01);
}
function showChange(coins) {
if (coins[3] > 0) {
$('.quarter').html(coins[3] + " quarter(s).");
}
if (coins[2] > 0) {
$('.dime').html(coins[2] + " dime(s).");
}
if (coins[1] > 0) {
$('.nickel').html(coins[1] + " nickel(s).");
}
if (coins[0] > 0) {
$('.penny').html(coins[0] + " pennies.");
}
}
makeChange(total, coins);
showChange(coins);
However, this seems awfully repetitive and I'm finding that with certain values, it's a penny off. How can I make it more accurate and concise?
I'm finding that with certain values, it's a penny off.
Probably due to floating-point issues. And you shouldn't use parseInt to convert a number - it's meant for strings.
this seems awfully repetitive
A loop, with a data structure that represent the different coins will help. You already did something like that for your result: coins is an array, not 4 different variables.
function makeChange(total, values) {
var coins = [],
epsilon = 1e-5; // this is wrong in general!
// assume values are ascending, so we loop backwards
for (var i=values.length; i--; ) {
coins[i] = Math.floor(total / values[i].val + epsilon);
total %= values[i].val;
}
return coins;
}
function showChange(coins, values) {
for (var i=values.length; i--; ) {
var el = $(values[i].sel);
if (coins[i] > 0) {
el.html(coins[i] + " "+values[i].name+".");
} else {
el.empty();
}
}
}
var values = [
{val:0.01, sel:'.penny', name:"pennies"},
{val:0.05, sel:'.nickel', name:"nickel(s)"},
{val:0.10, sel:'.dime', name:"dime(s)"},
{val:0.25, sel:'.quarter', name:"quarter(s)"}
];
showChange(makeChange(parseFloat($('#total').val()), values), values);
Your best bet to avoid rounding problems is to just multiple your total by 100 to convert your dollar amount into all pennies, then do you conversion. For example:
function makeChange(total, coins) {
var remainder = 0;
total = Math.round(total * 100);
coins[3] = Math.floor(total / 25);
remainder = total - coins[3] * 25;
total = remainder;
coins[2] = Math.floor(total / 10);
remainder = total - coins[2] * 10;
total = remainder;
coins[1] = Math.floor(total / 5);
remainder = total - coins[1] * 5;
total = remainder;
coins[0] = total;
}
http://jsfiddle.net/t14cwdph/4/
For making your code easier to manage - see #Bergi's answer.