I have a fixed tax value, say USD 50,00, and I want to divide this tax among people. So, one person can select how much of the tax he will pay. Once this person selects its quota, the remaining of the tax is divided among the others.
I have made a javascript(I am using EmberJs) function to do this automatically but sometimes the value is evaluated to more than USD 50 and sometimes less.
My function:
percentageFromValue(person, selectedValue){
selectedValue = selectedValue.replace(/[R$\s]/g,'');
selectedValue = selectedValue.replace(/[,]/g,'.');
selectedValue = parseFloat(selectedValue);
let taxValue= this.get('taxValue');
///nao deixar valor utrapasse o valor da taxa
if(selectedValue> taxValue)
valor = taxValue;
let personPercentage = (selectedValue*100.0 / taxValue);
personPercentage = parseFloat(personPercentage );
let parcialSum= 0;
person.set('pctTax',personPercentage.toFixed(2));
let remainingPercent= 100.0 - personPercentage ;
let totalPersons = this.get('persons.length');
let pctPerPerson= remainingPercent/ (totalPersons - 1);
let valuePerPerson= (pctPerPerson* taxValue) / 100.0;
this.get('persons').forEach(r =>{
if(person.get('id') != r.get('id')){
r.set('pctTax',pctPerPerson);
r.set('value',valuePerPerson.toFixed(2));
}
});
},
How Can I make this automatic redistributions to always sum up to USD 50,00??
This is more of a rounding problem than a programming problem.
Say you want to divide a $50 tax among three people... 50/3 = 16.6666666... assuming it's a currency and you round up to two decimals, each person pays $16.66 and the sum is 16.66 * 3 = 49.98.
If there is no requirement of having all people paying the exact same amount of tax every time, I'd just add/subtract the rounding difference from the first person:
let remainingPercent= 100.0 - personPercentage ;
let totalPersons = this.get('persons.length');
let pctPerPerson= remainingPercent/ (totalPersons - 1);
let valuePerPerson= (pctPerPerson* taxValue) / 100.0;
let roundingError = taxValue - pctPerPerson * totalPersons;
this.get('persons').forEach(r =>{
if(person.get('id') != r.get('id')){
r.set('pctTax',pctPerPerson);
if (this.indexOf(r) == 0) {
r.set('value',valuePerPerson.toFixed(2) + roundingError);
} else {
r.set('value',valuePerPerson.toFixed(2));
}
}
});
I have a small "problem". I try to do a Loop-for for a
"getElementsByName" for each rows in the table.
I try to loop a few values.
Price * Quantity * discount * tax (select.options) = MY Final price after discout.
AD: (You have to open Full View)
For a single line it works great by getElementById. However, the need for the creation of the next line (Button Add Position). So i chose GetElementsByName
Also counted for him the value (in place "after rebate")
--EDIT--
I made a loop "For".
In html code I have a lot the same fields "named" (ex. cena, ile, rabat etc.)
So if I will had 3 rows with this fields I want to calculate for each line separately. But my loop doesn't work.
Full View you can see here:
http://codepen.io/warhero/pen/WwvLZE (121 line JS)
My JS code:
var i;
for (i = 0; i < document.getElementsByName('kwotarabat').length; i++) {
var cena = parseInt(document.getElementsByName('cena')[i].value);
var ile = parseInt(document.getElementsByName('ile')[i].value);
var rabat = parseInt(document.getElementsByName('rabat')[i].value);
var vat = document.getElementsByName('vat')[i].options[document.getElementsByName('vat')[i].selectedIndex].value;
// vat value
var wynik = (ile * cena * vat);
// the net value
var wynik2 = cena * ile;
// net amount after discount
var wynikRabat = (wynik2 * (rabat / 100));
// gross amount after discount
var wynikRabatVat = (wynik * (rabat / 100));
// net amount after discount (display for customers)
var wynikNetto = (wynik2 - wynikRabat);
document.getElementsByName('kwotarabat')[i].innerHTML = (wynik + wynik2 - wynikRabat - wynikRabatVat).toFixed(2);
}
In Here >> http://codepen.io/warhero/pen/ONVEmZ is the code for a single row and calculations are correct.
Any Ideas ?
I'm trying to make it to where when a user does a certain thing, they get between 2 and 100 units. But for every 1,000 requests I want it to add up to 3,500 units given collectively.
Here's the code I have for adding different amounts randomly to a user:
if (Math.floor(Math.random() * 1000) + 1 === 900) {
//db call adding 100
}
else if (Math.floor(Math.random() * 100) + 1 === 90) {
//db call adding 40
}
else if (Math.floor(Math.random() * 30) + 1 === 20) {
//db call adding 10
}
else if (Math.floor(Math.random() * 5) + 1 === 4) {
//db call adding 5
}
else {
//db call adding 2
}
If my math is correct, this should average around 4,332 units per 1,000 calls. But obviously it would vary and I don't want that. I'd also like it to add random amounts instead, as the units added in my example are arbitrary.
EDIT: Guys, Gildor is right that I simply want to have 3,500 units, and give them away within 1,000 requests. It isn't even entirely necessary that it always reaches that maximum of 3,500 either (I could have specified that). The important thing is that I'm not giving users too much, while creating a chance for them to win a bigger amount.
Here's what I have set up now, and it's working well, and will work even better with some tweaking:
Outside of call:
var remaining = 150;
var count = 0;
Inside of call:
count += 1;
if (count === 100) {
remaining = 150;
count = 0;
}
if (Math.floor(Math.random() * 30) + 1 === 20) {
var addAmount = Math.floor(Math.random() * 85) + 15;
if (addAmount <= remaining) {
remaining -= addAmount;
//db call adding addAmount + 2
}
else {
//db call adding 2
}
}
else if (Math.floor(Math.random() * 5) + 1 === 4) {
var addAmount1 = Math.floor(Math.random() * 10) + 1;
if (addAmount1 <= remaining) {
remaining -= addAmount1;
//db call adding addAmount1 + 2
}
else {
//db call adding 2
}
}
else {
//db call adding 2
}
I guess I should have clarified, I want a "random" number with a high likelihood of being small. That's kind of part of the gimmick, where you have low probability of getting a larger amount.
As I've commented, 1,000 random numbers between 2 and 100 that add up to 3,500 is an average number of 3.5 which is not consistent with random choices between 2 and 100. You'd have to have nearly all 2 and 3 values in order to achieve that and, in fact couldn't have more than a couple large numbers. Nothing even close to random. So, for this to even be remotely random and feasible, you'd have to pick a total much large than 3,500. A random total of 1,000 numbers between 2 and 100 would be more like 51,000.
Furthermore, you can't dynamically generate each number in a truly random fashion and guarantee a particular total. The main way to guarantee that outcome is to pre-allocate random numbers that add up to the total that are known to achieve that and then random select each number from the pre-allocated scheme, then remove that from the choice for future selections.
You could also try to keep a running total and bias your randomness if you get skewed away form your total, but doing it that way, the last set of numbers may have to be not even close to random in order to hit your total consistently.
A scheme that could work if you reset the total to support what it should be for actual randomness (e.g. to 51,000) would be to preallocated an array of 500 random numbers between 2 and 100 and then add another 500 numbers that are the complements of those. This guarantees the 51 avg number. You can then select each number randomly from the pre-allocated array and then remove it form the array so it won't be selected again. I can add code to do this in a second.
function RandResults(low, high, qty) {
var results = new Array(qty);
var limit = qty/2;
var avg = (low + high) / 2;
for (var i = 0; i < limit; i++) {
results[i] = Math.floor((Math.random() * (high - low)) + low);
//
results[qty - i - 1] = (2 * avg) - results[i];
}
this.results = results;
}
RandResults.prototype.getRand = function() {
if (!this.results.length) {
throw new Error("getRand() called, but results are empty");
}
var randIndex = Math.floor(Math.random() * this.results.length);
var value = this.results[randIndex];
this.results.splice(randIndex, 1);
return value;
}
RandResults.prototype.getRemaining = function() {
return this.results.length;
}
var randObj = new RandResults(2, 100, 1000);
// get next single random value
if (randObj.getRemaining()) {
var randomValue = randObj.getRand();
}
Working demo for a truly random selection of numbers that add up to 51,000 (which is what 1,000 random values between 2 and 100 should add up to): http://jsfiddle.net/jfriend00/wga26n7p/
If what you want is the following: 1,000 numbers that add up to 3,500 and are selected from between the range 2 to 100 (inclusive) where most numbers will be 2 or 3, but occasionally something could be up to 100, then that's a different problem. I wouldn't really use the word random to describe it because it's a highly biased selection.
Here's a way to do that. It generates 1,000 random numbers between 2 and 100, keeping track of the total. Then, afterwards it corrects the random numbers to hit the right total by randomly selected values and decrementing them until the total is down to 3,500. You can see it work here: http://jsfiddle.net/jfriend00/m4ouonj4/
The main part of the code is this:
function RandResults(low, high, qty, total) {
var results = new Array(qty);
var runningTotal = 0, correction, index, trial;
for (var i = 0; i < qty; i++) {
runningTotal += results[i] = Math.floor((Math.random() * (high - low)) + low);
}
// now, correct to hit the total
if (runningTotal > total) {
correction = -1;
} else if (runningTotal < total) {
correction = 1;
}
// loop until we've hit the total
// randomly select a value to apply the correction to
while (runningTotal !== total) {
index = Math.floor(Math.random() * qty);
trial = results[index] + correction;
if (trial >= low && trial <= high) {
results[index] = trial;
runningTotal += correction;
}
}
this.results = results;
}
This meets an objective of a biased total of 3,500 and all numbers between 2 and 100, though the probability of a 2 in this scheme is very high and the probably of a 100 in this scheme is almost non-existent.
And, here's a weighted random generator that adds up to a precise total. This uses a cubic weighting scheme to favor the lower numbers (the probably of a number goes down with the cube of the number) and then after the random numbers are generated, a correction algorithm applies random corrections to the numbers to make the total come out exactly as specified. The code for a working demo is here: http://jsfiddle.net/jfriend00/g6mds8rr/
function RandResults(low, high, numPicks, total) {
var avg = total / numPicks;
var i, j;
// calculate probabilities for each value
// by trial and error, we found that a cubic weighting
// gives an approximately correct sub-total that can then
// be corrected to the exact total
var numBuckets = high - low + 1;
var item;
var probabilities = [];
for (i = 0; i < numBuckets; i++) {
item = low + i;
probabilities[i] = avg / (item * item * item);
}
// now using those probabilities, create a steps array
var sum = 0;
var steps = probabilities.map(function(item) {
sum += item;
return sum;
});
// now generate a random number and find what
// index it belongs to in the steps array
// and use that as our pick
var runningTotal = 0, rand;
var picks = [], pick, stepsLen = steps.length;
for (i = 0; i < numPicks; i++) {
rand = Math.random() * sum;
for (j = 0; j < stepsLen; j++) {
if (steps[j] >= rand) {
pick = j + low;
picks.push(pick);
runningTotal += pick;
break;
}
}
}
var correction;
// now run our correction algorithm to hit the total exactly
if (runningTotal > total) {
correction = -1;
} else if (runningTotal < total) {
correction = 1;
}
// loop until we've hit the total
// randomly select a value to apply the correction to
while (runningTotal !== total) {
index = Math.floor(Math.random() * numPicks);
trial = picks[index] + correction;
if (trial >= low && trial <= high) {
picks[index] = trial;
runningTotal += correction;
}
}
this.results = picks;
}
RandResults.prototype.getRand = function() {
if (!this.results.length) {
throw new Error("getRand() called, but results are empty");
}
return this.results.pop();
}
RandResults.prototype.getAllRand = function() {
if (!this.results.length) {
throw new Error("getAllRand() called, but results are empty");
}
var r = this.results;
this.results = [];
return r;
}
RandResults.prototype.getRemaining = function() {
return this.results.length;
}
As some comments pointed out... the numbers in the question does not quite make sense, but conceptually there are two approaches: calculate dynamically just in time or ahead of time.
To calculate just in time:
You can maintain a remaining variable which tracks how many of 3500 left. Each time when you randomly give some units, subtract the number from remaining until it goes to 0.
In addition, to make sure each time at least 2 units are given, you can start with remaining = 1500 and give random + 2 units each time.
To prevent cases that after 1000 gives there are still balances left, you may need to add some logic to give units more aggressively towards the last few times. However it will result in not-so-random results.
To calculate ahead of time:
Generate a random list with 1000 values in [2, 100] and sums up to 3500. Then shuffle the list. Each time you want to give some units, pick the next item in the array. After 1000 gives, generate another list in the same way. This way you get much better randomized results.
Be aware that both approaches requires some kind of shared state that needs to be handled carefully in a multi-threaded environment.
Hope the ideas help.
I'm having a very difficult time trying to figure out how to split a discount between two totals. Example i have a fixed discount of 100 and two totals one is 5000 the other is 468. So of that 100 like 95% is given to the 5000 and the other 5% is given to the 468. Any direction would help thank you and this is my code thus far.
subtotalDiscount = discount / 100 * subTotal;
nonTaxableTotalDiscount = discount / 100 * nonTaxableTotal;
1) 100/(5000+468) * 5000
2) 100/(5000+468) * 468
I think what you're looking for is just a way to make these values calculate automatically based on some fixed discount. Here is something you could base it on:
largeSub = 5000;
smallSub = 468;
fixedDiscount = 100;
largeDiscountPercent = .95;
smallDiscountPercent = .05;
largeTotal = largeSub - fixedDiscount * largeDiscountPercent;
smallTotal = smallSub - fixedDiscount * smallDiscountPercent;
I'm creating a HR Mileage and Expenses system but am struggling to come up with a way of calculating the rates correctly.
There are 2 rates for car, motorbike, and bicycle. One rate for upto 10,000 miles one rate for over 10,000 miles.
Lets just take car rates as an example. Currently it's 45pence per mile up to 10,000 miles and 25pence per mile there after.
So I have the variables to hold the business mileage and keep it adding but how can I handle the change over of rates?
For example: BusinessMiles = 9990, Mileage Claimed = 100.
So I need to check the business miles are less than 10,000 then the difference between the business miles and the limit. which is 10 miles # 0.45 and 90 miles # 0.25.
With Chris's pointers here's my output:
//calculate mileage
var businessMilesClaimed = "100";
var currentMilesClaimed = "12110";
if (currentMilesClaimed < 10000)
{
var claimedAmount = +businessMilesClaimed + +currentMilesClaimed;
if (claimedAmount > 10000)
{
var claimCalc1 = (claimedAmount - 10000) * 0.25;
var claimCalc2 = (10000 - currentMilesClaimed) * 0.45;
var claimResult = +claimCalc1 + +claimCalc2;
}
else
{
var claimResult = businessMilesClaimed * 0.45;
}
}
else
{
var claimResult = businessMilesClaimed * 0.25;
}
This seems like something you could definitely have tackled. As such, here is some pseudocode to help you:
milage := 11,192.
// milage is the amount of miles driven..
if(milage is greater than 10000)
// If they've driven more than ten thousand miles, calculate the difference.
milage := 10000.
changeOverMilage := milage - 10000.
else
// Otherwise, there is no changeOverMilage so set it to 0.
changeOverMilage = 0.
// Calculate the cost.
cost := (milage * 0.45) + (changeOverMilage * 0.25)