Javascript Floating Point Multiply by 100 Still has Errors - javascript

I have a text input for a money field.
I enter 33.91 into the field, and get the following results while trying to use the 'multiply by 100' technique.
var curWth = parseInt($('#trans_withdraw'+index).val()*100); // 3390
var curWth = parseInt($('#trans_withdraw'+index).val())*100; // 3300
var curWth = $('#trans_withdraw'+index).val()*100; // 3390.9999999...5
var curWth = parseFloat($('#trans_withdraw'+index).val())*100; // 3390.9999999...5
var curWth = parseFloat($('#trans_withdraw'+index).val()*100); // 3390.9999999...5
None of these give me 3391. I thought the whole idea of multiplying by 100 was to get away from the floating point problem. But as line 3 shows, when I multiply the value by 100 immediately, I still get floating point errors.
What am I still not understanding about working with currency?
I know 0.1 can't be stored correctly as a float. But multiplying by 100 is also not working for me in this case.

praseFloat to get your decimal value then multiple by 100 to get 3390.9999 then Math.round() to get the value.
var number = parseFloat($('#trans_withdraw').val()).toFixed(2);
var value = number * 100;
console.log(Math.round(value));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="trans_withdraw" value="33.91" />

Related

how to get percentage a day to more precision from javascript momentjs.asHours()?

I have table like this:
The total of the Percentage column must be 100%, but I'm getting 100.01%.
Here's my code:
var hourSlow = $("#input-me-slow").val();
var slowTime = moment.duration(hourSlow).asHours();
// slow time return 2.1666666666666665
var hourIdle = $("#input-me-idle").val();
var idleTime = moment.duration(hourIdle).asHours()
// idle time return 1
var hourEco = $("#input-me-eco").val();
var ecoTime = moment.duration(hourEco).asHours();
// ecoTime return 20.166666666666668
var hourSpeed = $("#input-me-speed").val();
var speedTime = moment.duration(hourSpeed).asHours();
// speedTime return 0.6666666666666666
var fTime = "24:00"
var dfTime = moment.duration(fTime).asHours();
// dfTime return 24
var totalTime = dfTime-speedTime-ecoTime-slowTime-idleTime;
// totalTime return -2.220446049250313e-15
// Here for display it to table, the problem is here
var fPercent = toHour(fullTime); //return 2.78
var ePercent = toHour(ecoTime); //return 84.03
var sPercent = toHour(slowTime); //return 9.03
var iPercent = toHour(idleTime); //return 4.17
$("#me_fullpercen").text(addCommas(fPercent));
$("#me_ecopercen").text(addCommas(ePercent));
$("#me_slowpercen").text(addCommas(sPercent));
$("#me_idlepercen").text(addCommas(iPercent));
// here the function of toHour (I dont know maybe the problem is here)
function toHour(num) {
var result = (num / 24) * 100;
return result ;
}
I would rather not round the percentage to 100%, as that would be less precise.
How can I make my percentage 100% instead of 100.01%?
This is a common problem, and no matter how precise you try to be, the computer will need to round numbers with repeating decimals at some point. Here's some posts that deal with it:
How to make rounded percentages add up to 100%
How to deal with the sum of rounded percentage not being 100?
In those posts you can read about many complex ways to get very close to 100%, but basically there is no right way to do this - when it's all boiled down it's still going to be an estimate - not exactly precise because we're dealing with not-precise numbers. That's just the nature of the beast.
Your program is going to round numbers the wrong way because it's a computer, and it's not intelligent.
Depending on your application, you may want to invest time into reading how to do those complex methods, and maybe you'll get really close.
Add a Footnote
Any path you choose, you'll probably end up putting a footnote explaining this problem anyway. Something like this:
*Because of rounding, these values may not add up to 100%.

Javascript, rounding and calculating values against original values

I'm trying to calculate a series of values which should aggregate to the same as the Original Value.
If you look at the above example, you can see that the aggregated cost and billed figures are aggregating to 239.99 and 219.98 respectively. They obviously need to aggregate to 240 and 220 respectively.
The cost and billed figures are calculated when Hours changes (by using a jQuery on change function). The multiplier is determined by dividing the Original Value Hours by the number specified in the Calculated Values Hours below.
(0.2 / 0.7) = 0.28571428571428575
(0.3 / 0.7) = 0.4285714285714286
Self-evidently, the figures need to aggregate to the Original Values.
This is an issue no doubt to do with floating point precision and rounding and I've tried using the following function without success:-
function to2DP(num, fixed) {
var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
return num.toString().match(re)[0];
}
$("#splitTimeContainer").on("change", ".changeHours", function(e) {
var splitID = $("#splitID").val();
var splitOrigCost = $("#splitOrigCost").val();
var splitOrigBilled = $("#splitOrigBilled").val();
var splitOrigHours = $("#splitOrigHours").val();
var i = 1;
var divideMe = $(this).val();
var coEfficient = (divideMe/splitOrigHours);
var newCost = to2DP((coEfficient * splitOrigCost), 2);
var newBilled = to2DP((coEfficient * splitOrigBilled), 2);
var parent = $(this).parent().parent();
parent.find('.changeCost').val(newCost);
parent.find('.changeBilled').val(newBilled);
});
As well as using toFixed, but again without success.
Anyone have any suggestions at how I go about achieving this?
This question is more about rounding and mathematics.
I recommend to use different rounding to even. This rounding at least has no bias so it will not systematically increase or decrease values.
Another problem is that even with this rounding there is no guarantee that sum of values will match due to odd number of calculated values.
In this particular example this rounding will achieve cost 240 and billed 220.01.
This problem in my opinion has not optimal solution.
Consider this:
Hours: 0.9, Cost 100
hours: 0.3, cost 33.33
hours: 0.3, cost 33.33
hours: 0.3, cost 33.33
There is no way how to make this working.
You might want to consider adding the amount lost during division to one or more values.
Splitwise also does that to ensure no loss of value.

Javascript roundup decimal values if decimal value is greater than or equal to 25 then round up value by plus one other wise remain as it is

I want to round up a decimal value in JavaScript. I need functionality something like below :
if decimal value is grater than or equal to 25 then i want to round up a value by plus one.
eg. if value = 5.56789 then new value should be 6
I know using if condition it is possible.
I have done using if condition like below :
<!DOCTYPE html>
<html>
<body>
<p>Click the button to display the fixed number.</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
<script>
function myFunction() {
var num = 5.24389;
var n = num.toFixed(2)
var num_arr = n.split('.');
var newval = num_arr[0];
if(num_arr[1] >= 25)
{
newval++;
}
document.getElementById("demo").innerHTML = newval;
}
</script>
</body>
</html>
But i don't want to use any conditions.
So is there any JavaScript function which do like my example?
Any help would be appreciated!!
So the question here is how can you shift the rounding point so it is .25 instead of .50. The basic idea is you need to subtract .25 and round up to the nearest whole number.
If we are dealing with two decimal max it is simple, we subtract .24 and use ceil().
function roundUpOverQuarter(num) {
return Math.ceil(num - .24);
}
console.log("1", roundUpOverQuarter(1));
console.log("1.24", roundUpOverQuarter(1.24));
console.log("1.25", roundUpOverQuarter(1.25));
console.log("1.5", roundUpOverQuarter(1.5));
Now the code above works with "money" value, only two decimals.To deal with greater than two decimals, it requires a bit more math. You would need to first chop it to two decimals by shifting the number up two, floor it, to drop the decimals, then shift the number back so we can follow the same process we did above.
function roundUpOverQuarter(num) {
num = Math.floor((num*100))/100;
return Math.ceil(num - .24);
}
console.log("1", roundUpOverQuarter(1));
console.log("1.24", roundUpOverQuarter(1.24));
console.log("1.25", roundUpOverQuarter(1.25));
console.log("1.5", roundUpOverQuarter(1.5));
console.log("1.24999", roundUpOverQuarter(1.24999)); //would fail with the first solution

Javascript .val() issue

When I enter a decimal for chance, it returns NaN for pay and profit. Any idea why? Also what would I need to do to round profit to the second decimal.
Thanks.
$(document).ready(function(){
function updateValues() {
// Grab all the value just incase they're needed.
var chance = $('#chance').val();
var bet = $('#bet').val();
var pay = $('#pay').val();
var profit = $('#profit').val();
// Calculate the new payout.
var remainder = 101 - chance;
pay = Math.floor((992/(chance+0.5)) *100)/100;
// Calculate the new profit.
profit = bet*pay-bet;
// Set the new input values.
$('#chance').val(chance);
$('#bet').val(bet);
$('#pay').val(pay);
$('#profit').val(profit);
}
$('#chance').keyup(updateValues);
$('#bet').keyup(updateValues);
$('#pay').keyup(updateValues);
$('#profit').keyup(updateValues);
});
First make use of parseFloat or (parseInt if you don't need float values).
function updateValues() {
var chance = parseFloat($('#chance').val());
var bet = parseFloat($('#bet').val());
var pay = parseFloat($('#pay').val());
var profit = parseFloat($('#profit').val());
// Calculate the new payout.
var remainder = 101 - chance;
pay = Math.floor((992/(chance+0.5)) *100)/100;
}
Also what would I need to do to round profit to the second decimal.
you can do this:
profit = bet*pay-bet;
profit = profit.toFixed(2);
You need to use parseFloat to properly work with the values, which by default are strings:
var chance = parseFloat($('#pay').val());
/*same for other values*/
To round the profit to 2 decimals, you can use toFixed on that number, which again converts it back to a string.
3.123.toFixed(2) = "3.12"
Try using parseFloat:
var chance = parseFloat($("#Chance").val());
You can also use toFixed to specify the number of decimal places.
Edit
You need to modify chance:
chance = parseFloat(chance);
You can see this working here:
http://jsfiddle.net/U8bpX/

JavaScript parseFloat() issue

Okay so my code works fine but when a decimal i.e. 60.1, 60.2, 60.3, etc. is input for #chance it screws up profit and pay.
For example: 60% is input for chance, 1 for bet. It returns 1.65 for pay and 0.65 for profit. That's all correct.
But when I put 60.1, it returns 16.5 ( wrong decimal ) and 15.5 for profit. 16.5 seems like an easy fix but Idk how to fix it, but I have no idea why it's returning 15.5 for profit and thought maybe if I fixed pay it would fix the issue with profit.
What's wrong?
Thanks.
<script>
$(document).ready(function(){
function updateValues() {
// Grab all the value just incase they're needed.
var chance = $('#chance').val();
var bet = $('#bet').val();
var pay = $('#pay').val();
var profit = $('#profit').val();
// Calculate the new payout.
var remainder = 101 - chance;
pay = Math.floor((992/parseFloat((chance+0.5))) *100)/100;
// Calculate the new profit.
profit = bet*pay-bet;
profit = profit.toFixed(6);
// Set the new input values.
$('#chance').val(chance);
$('#bet').val(bet);
$('#pay').val(pay);
$('#profit').val(profit);
}
parseInt($('#chance').keyup(updateValues));
parseInt($('#bet').keyup(updateValues));
parseInt($('#pay').keyup(updateValues));
parseInt($('#profit').keyup(updateValues));
});
</script>
parseFloat((chance+0.5))
looks very wrong. chance is a string, so the + operator will perform string concatenation. When you input 60, it becomes
parseFloat("60"+0.5) === 600.5
while when you input 60.1 it is
parseFloat("60.1"+0.5) === 60.1
You probably wanted
(992/(parseFloat(chance)+0.5))*100
// or
(992/parseFloat(chance)+0.5)*100
// or
992/parseFloat(chance)*100+0.5
// or something along these lines
Change parseFloat((chance+0.5)) into (parseFloat(chance)+0.5).
Actually, I can't see why it's working with 60, either. chance, as a value of a text field, is a string: "60". Strings don't add, they concatenate: "60" + 0.5 is "600.5", same as "60" + "0.5".
Try something like this:
$(document).ready(function(){
function updateValues(){
var chance = $('#chance').val();
var bet = $('#bet').val();
var pay = $('#pay').val();
var profit = $('#profit').val();
pay = ((992/Math.floor(+chance+0.5))/10).toFixed(2);
profit = (bet*pay-bet).toFixed(6);
$('#chance').val(chance);
$('#bet').val(bet);
$('#pay').val(pay);
$('#profit').val(profit);
}
$('#chance').keyup(updateValues);
$('#bet').keyup(updateValues);
$('#pay').keyup(updateValues);
$('#profit').keyup(updateValues);
});
Something is wrong with your Math.
Note:
You don't have to use parseInt() or parseFloat() to make Strings to Numbers. the + symbol in front of your String that is a Number will convert it to a Number.
See http://jsfiddle.net/PHPglue/JQJMD/ for more details.

Categories

Resources