Trying to round an object value in javascript - javascript

I have seemingly a very simple little script...
function speedcomp(obj) {
obj.speedmile.value = 3600 / obj.timesec.value
}
function distcomp(obj) {
if (obj.speed.value == "")
obj.speed.value = ((1 * obj.distance.value) / obj.day.value) / 24;
else if (obj.distance.value == "")
obj.distance.value = distance.value;
else if (obj.day.value == "")
obj.day.value = ((1 * obj.distance.value) / obj.speed.value) / 24;
obj.hour.value = ((1 * obj.distance.value) / obj.speed.value);
}​
I have 4 input type text's with id's of distance, speed, day, and hour. When I put in a speed and distance and click a button who's onclick="distcomp(this.form)" it does the math for me nicely.
The issue I am having is trying to round the values for day and hour to the nearest 100th. Since I am not presetting the values I am finding my self struggling with Math.round and Math.floor. I believe the answer will be using Math.round but I could use some.
Thank you in advance.

You could just use toFixed:
var num = Math.random();
alert(num.toFixed(2));
There are some buggy implementations around IE 6, and javascript decimals aren't precise for some values so you might get unexpected results:
(0.595).toFixed(2) // 0.59 in Firefox, 0.60 in IE
If you use:
Math.round(num*100)/100
then you will not get the right padding (0.59 => 0.6 not 0.60). MDN has some other interesting snippets.
There seems to be a reasonable replacement for toFixed in answer to How to write a prototype for Number.toFixed in JavaScript?.
Edit
Here is a reasonable toFixed function, I'll keep testing to make sure it's reasonably ES5 compliant. For toFixed(0,2) it returns 0.00 whereas the spec says 0 but I think the former is more useful.
function toFixed(num, places) {
var m, s = '', t;
num = Number(num);
if (isNaN(num)) return 'NaN';
if (num < 0) {
s = '-';
num = num * -1;
}
m = Math.pow(10, places || 0);
num = String(Math.round(num * m) / m).split('.');
t = num[1] || '';
num[1] = t + (new Array(places - t.length + 1)).join('0');
return s + num.join('.');
};
Jasper's comment seems like a good solution:
(Math.round(.595*100)/100).toFixed(2);
though (0).toFixed(2) gives 0 (per EMCA-262) rather than the more useful 0.00, which is why the above avoids toFixed.

To round to the nearest 100th, multiply the number by 100, call Math.round() and then divide by 100 again.
num=210.653434343
Math.round(num*100)/100
210.65
To round to the 100s place, divide first, round, then multiply. You can also change 100 to any other place and it will work for that. (change 100 to 10 for 10s and 10ths place)

Related

How to truncate decimals in JavaScript without Math library?

I need numbers to have only 2 decimals (as in money), and I was using this:
Number(parseFloat(Math.trunc(amount_to_truncate * 100) / 100));
But I can no longer support the Math library.
How can I achieve this without the Math library AND withou rounding the decimals?
You can use toFixed
Number(amount_to_truncate.toFixed(2))
If you are sure that your input always will be lower or equal than 21474836.47 ((2^31 - 1) / 100) (32bit) then:
if you need as string (to make sure result will have 2 decimals)
((amount_to_truncate * 100|0)/100).toFixed(2)
Otherwise
((amount_to_truncate * 100|0)/100)
Else: See Nina Schols's answer
console.log((((15.555 * 100)|0)/100)) // will not round: 15.55
console.log((((15 * 100)|0)/100).toFixed(2)) // will not round: 15.55
Make it simple
const trunc = (n, decimalPlaces) => {
const decimals = decimalPlaces ? decimalPlaces : 2;
const asString = n.toString();
const pos = asString.indexOf('.') != -1 ? asString.indexOf('.') + decimals + 1 : asString.length;
return parseFloat(n.toString().substring(0, pos));
};
console.log(trunc(3.14159265359));
console.log(trunc(11.1111111));
console.log(trunc(3));
console.log(trunc(11));
console.log(trunc(3.1));
console.log(trunc(11.1));
console.log(trunc(3.14));
console.log(trunc(11.11));
console.log(trunc(3.141));
console.log(trunc(11.111));
The only thing I see wrong with toFixed is that it rounds the precision which OP specifically states they don't want to do. Truncate is more equivalent to floor for positive numbers and ceil for negative than round or toFixed. On the MDN page for the Math.trunc there is a polyfill replacement function that would do what OP is expecting.
Math.trunc = Math.trunc || function(x) {
return x - x % 1;
}
If you just used that, then the code wouldn't have to change.
You could use parseInt for a non rounded number.
console.log(parseInt(15.555 * 100, 10) / 100); // 15.55 no rounding
console.log((15.555 * 100 | 0) / 100); // 15.55 no rounding, 32 bit only
console.log((15.555).toFixed(2)); // 15.56 rounding
Try using toFixed:
number.toFixed(2)
Truncate does also a rounding, so your statement: "I need numbers to have only 2 decimals ... without rounding the decimals" seems to me a little bit convoluted and would lead to a long discussion.
Beside this, when dealing with money, the problem isn't Math but how you are using it. I suggest you read the Floating-point cheat sheet for JavaScript - otherwise you will fail even with a simple calculation like 1.40 - 1.00.
The solution to your question is to use a well-tested library for arbitrary-precision decimals like bignumber.js or decimals.js (just as an example).
EDIT:
If you absolutely need a snippet, this is how i did it some time ago:
function round2(d) { return Number(((d+'e'+2)|0)+'e-'+2); }
You could parseInt to truncate, then divide by 100 and parseFloat.
var num = 123.4567;
num=parseInt(num*100);
num=parseFloat(num/100);
alert(num);
See fiddle
Edit: in order to deal with javascript math craziness, you can use .toFixed and an additional digit of multiplication/division:
var num = 123.4567;
num = (num*1000).toFixed();
num = parseInt(num/10);
num = parseFloat(num/100);
alert(num);
Updated fiddle
This was a lot easier than I thought:
const trunc = (number, precision) => {
let index = number.toString().indexOf(".");
let subStr;
// in case of no decimal
if (index === -1) {
subStr = number.toString();
}
// in case of 0 precision
else if (precision === 0) {
subStr = number.toString().substring(0, index);
}
// all else
else {
subStr = number.toString().substring(0, index + 1 + precision);
}
return parseFloat(subStr);
};
let x = trunc(99.12, 1);
console.log("x", x);
You can try this
function trunc(value){
return (!!value && typeof value == "number")? value - value%1 : 0;
}
console.log(trunc(1.4));
console.log(trunc(111.9));
console.log(trunc(0.4));
console.log(trunc("1.4"));

Round number to nearest .5 decimal

I'm looking for an output of
4.658227848101266 = 4.5
4.052117263843648 = 4.0
the closest I've gotten is
rating = (Math.round(rating * 4) / 4).toFixed(1)
but with this the number 4.658227848101266 = 4.8???
(Math.round(rating * 2) / 2).toFixed(1)
It's rather simple, you should multiply that number by 2, then round it and then divide it by 2:
var roundHalf = function(n) {
return (Math.round(n*2)/2).toFixed(1);
};
This works for me! (Using the closest possible format to yours)
rating = (Math.round(rating * 2) / 2).toFixed(1)
So this answer helped me. Here is a little bit o magic added to it to handle rounding to .5 or integer. Notice that the *2 and /2 is switched to /.5 and *.5 compared to every other answer.
/*
* #param {Number} n - pass in any number
* #param {Number} scale - either pass in .5 or 1
*/
var superCoolRound = function(n,scale) {
return (Math.round(n / scale) * scale).toFixed(1);
};
This is kinda late. But for someone who wants to round down to whole number or 0.5, you can try this:
function roundDown(number) {
var decimalPart = number % 1;
if (decimalPart < 0.5)
return number - decimalPart;
else
return number - decimalPart + 0.5;}
Late to this party, but I thought I would throw in a nice answer using a syntax I saw elsewhere, just in case someone comes across this in the future.
const roundDown = decimalNumber => {
return decimalNumber % 1 >= 0.5 ? +`${~~decimalNumber}.5` : ~~decimalNumber;
}
Explanation:
decimalNumber % 1 leaves you with only the decimal places
The + converts the string representation of your constructed number into a float, for consistency
~~decimalNumber drops the decimal places, leaving you with an integer
I assume you want to format the number for output and not truncate the precision. In that case, use a DecimalFormat. For example:
DecimalFormat df = new DecimalFormat("#.#");
df.format(rating);

How can I fix these calculations?

I'm taking a number, dividing by 100 and then multiplying it by 100 to have it return to it's original value. Some returned values are a little off however.
var num = 57,
num = num / 100,
// this should return the number to the original
// however in this example it returns 56.99999999999999
num = num * 100;
Here's a fiddle: http://jsfiddle.net/njsdW/
In truth, all I want to do is add two 0's in front of the number, but I'm not always sure where the decimal would be.
EDIT: My solution:
var num = 57,
num = (parseFloat((num / 100).toPrecision(15)));
// this should return the number to the original
num = (parseFloat((num * 100).toPrecision(15)));
You must save the precision of your number and restore it after dividing by 100
prec = num.length;
// adjust for decimal point
if (num.indexOf('.') != -1)
prec--;
// adjust for leading zero
if (num < 1)
prec--;
num /= 100;
self.find('h2').append(num.toPrecision(prec));
JSFiddle
You can use a JavaScript bignum implementation like javascript-bignum or gmp.js to get arbitrary precision. If you want to use gmp.js, you'd have to rewrite your application in C/C++ or write gmp.js bindings for JavaScript. In return, you'd get the battle-tested reliability and optimal algorithmic effenciency from GNU GMP.

Rounding up to the nearest 0.05 in JavaScript

Question
Does anyone know of a way to round a float to the nearest 0.05 in JavaScript?
Example
BEFORE | AFTER
2.51 | 2.55
2.50 | 2.50
2.56 | 2.60
Current Code
var _ceil = Math.ceil;
Math.ceil = function(number, decimals){
if (arguments.length == 1)
return _ceil(number);
multiplier = Math.pow(10, decimals);
return _ceil(number * multiplier) / multiplier;
}
Then elsewhere...
return (Math.ceil((amount - 0.05), 1) + 0.05).toFixed(2);
Which is resulting in...
BEFORE | AFTER
2.51 | 2.55
2.50 | 2.55
2.56 | 2.65
Multiply by 20, then divide by 20:
(Math.ceil(number*20)/20).toFixed(2)
Rob's answer with my addition:
(Math.ceil(number*20 - 0.5)/20).toFixed(2)
Otherwise it always rounds up to the nearest 0.05.
** UPDATE **
Sorry has been pointed out this is not what the orig poster wanted.
I would go for the standard of actually dividing by the number you're factoring it to, and rounding that and multiplying it back again after. That seems to be a proper working method which you can use with any number and maintain the mental image of what you are trying to achieve.
var val = 26.14,
factor = 0.05;
val = Math.round(val / factor) * factor;
This will work for tens, hundreds or any number. If you are specifically rounding to the higher number then use Math.ceil instead of Math.round.
Another method specifically for rounding just to 1 or more decimal places (rather than half a place) is the following:
Number(Number(1.5454545).toFixed(1));
It creates a fixed number string and then turns it into a real Number.
I would write a function that does it for you by
move the decimal over two places (multiply by 100)
then mod (%) that inflatedNumber by 5 and get the remainder
subtract the remainder from 5 so that you know what the 'gap'(ceilGap) is between your number and the next closest .05
finally, divide your inflatedNumber by 100 so that it goes back to your original float, and voila, your num will be rounded up to the nearest .05.
function calcNearestPointZeroFive(num){
var inflatedNumber = num*100,
remainder = inflatedNumber % 5;
ceilGap = 5 - remainder
return (inflatedNumber + ceilGap)/100
}
If you want to leave numbers like 5.50 untouched you can always add this checker:
if (remainder===0){
return num
} else {
var ceilGap = 5 - remainder
return (inflatedNumber + ceilGap)/100
}
You need to put -1 to round half down and after that multiply by -1 like the example down bellow.
<script type="text/javascript">
function roundNumber(number, precision, isDown) {
var factor = Math.pow(10, precision);
var tempNumber = number * factor;
var roundedTempNumber = 0;
if (isDown) {
tempNumber = -tempNumber;
roundedTempNumber = Math.round(tempNumber) * -1;
} else {
roundedTempNumber = Math.round(tempNumber);
}
return roundedTempNumber / factor;
}
</script>
<div class="col-sm-12">
<p>Round number 1.25 down: <script>document.write(roundNumber(1.25, 1, true));</script>
</p>
<p>Round number 1.25 up: <script>document.write(roundNumber(1.25, 1, false));</script></p>
</div>
I ended up using this function in my project, successfully:
roundToNearestFiveCents( number: any ) {
return parseFloat((Math.round(number / 0.05) * 0.05).toFixed(2));
}
Might be of use to someone wanting to simply round to the nearest 5 cents on their monetary results, keeps the result a number, so if you perform addition on it further it won't result in string concatenation; also doesn't unnecessarily round up as a few of the other answers pointed out. Also limits it to two decimals, which is customary with finance.
My solution and test:
let round = function(number, precision = 2, rounding = 0.05) {
let multiply = 1 / rounding;
return parseFloat((Math.round(number * multiply) / multiply)).toFixed(precision);
};
https://jsfiddle.net/maciejSzewczyk/7r1tvhdk/40/
Even though the OP is not explicit about banker rounding, rounding up to the nearest $0.05 (5 cents) should be compatible with banker rounding. What suggested by Arth is more accurate than the accepted answer by Rob W.
(Math.ceil(number*20 - 0.5)/20).toFixed(2)
With banker rounding, you need a basic banker rounding function as suggested at Gaussian/banker's rounding in JavaScript, and I rewrite in TypeScript:
static bankerRound(num: number, decimalPlaces?: number) {
const d = decimalPlaces || 0;
const m = Math.pow(10, d);
const n = +(d ? num * m : num).toFixed(8);
const i = Math.floor(n), f = n - i;
const e = 1e-8;
const r = (f > 0.5 - e && f < 0.5 + e) ?
((i % 2 === 0) ? i : i + 1) : Math.round(n);
return d ? r / m : r;
}
static roundTo5cents(num: number) {
const r = bankerRound(Math.ceil(num * 20 - 0.5) / 20, 2);
return r;
}
The correctness of this algorithm could be verified through MBS Online, e.g. http://www9.health.gov.au/mbs/ready_reckoner.cfm?item_num=60

Round money to nearest 10 dollars in Javascript

How can I round a decimal number in Javascript to the nearest 10? My math is pretty rubbish today, it could be the 2 hour sleep :/
Some sample cases
$2823.66 = $2820
$142.11 = $140
$9.49 = $10
I understand I probably need a combination of Math.round/floor but I can't seem to get expected result.
Any help/pointers appreciated!
M
Try
Math.round(val / 10) * 10;
Use this function:
function roundTen(number)
{
return Math.round(number/10)*10;
}
alert(roundTen(2823.66));
To round a number to the nearest 10, first divide it by 10, then round it to the nearest 1, then multiply it by 10 again:
val = Math.round(val/10)*10;
This page has some details. They go the other way (e.g., rounding to the nearest 0.01) but the theory and practice are identical - multiply (or divide), round, then divide (or multiply).
10 * Math.round(val / 10)
function round(number, multiplier) {
multiplier = multiplier || 1;
return Math.round(number / multiplier) * multiplier;
}
var num1 = 2823.66;
var num2 = 142.11;
var num3 = 9.49;
console.log(
"%s\n%s\n%s", // just a formating thing
round(num1, 10), // 2820
round(num2, 10), // 140
round(num3, 10) // 10
);

Categories

Resources