Rounding away from zero in Javascript - javascript

We are building a table in Javascript with Handsontable representing currency amounts. We give the user the possibility of render the amounts with two decimal places or no decimal places (it's a requirement from the client). And then we find things like this:
Column A Column B Column C = A + B
-------------------------------------------
-273.50 273.50 0 Two decimals
-273 274 0 No decimals
Investigating a little we came to find that the basic rounding function in Javascript, Math.round(), works like this:
If the fractional portion is exactly 0.5, the argument is rounded to the next integer in the direction of +∞. Note that this differs from many languages' round() functions, which often round this case to the next integer away from zero, instead (giving a different result in the case of negative numbers with a fractional part of exactly 0.5).
As we are dealing with currency amounts, we do not care about what happens after the second decimal place, so we chose to add -0.0000001 to any negative value in the table. Thus, when rendering the values with two or no decimals, now we get the proper results, as Math.round(-273.5000001) = -274, and Math.round(-273.4900001) is still -273.
Nonetheless, we would like to find a finer solution to this problem. So what is the best, most elegant way to achieve this (that does not require modifying the original numeric value)? Note that we do not directly call Math.round(x), we just tell Handsontable to format a value with a given number of decimal places.

Just some variations on how you could implement the desired behaviour, with or without using Math.round(). And the proof that these functions work.
It's up to you which version speaks to you.
const round1 = v => v<0 ? Math.ceil(v - .5) : Math.floor(+v + .5);
const round2 = v => Math.trunc(+v + .5 * Math.sign(v));
const round3 = v => Math.sign(v) * Math.round(Math.abs(v));
const round4 = v => v<0 ? -Math.round(-v): Math.round(v);
const funcs = [Number, Math.round, round1, round2, round3, round4];
[
-273.50, -273.49, -273.51,
273.50, 273.49, 273.51
].forEach(value => console.log(
Object.fromEntries(funcs.map(fn => [fn.name, fn(value)]))
));

Math.round() works as wanted for zero and positive numbers. For negative numbers, convert to a positive and then multiply back:
/**
* #arg {number} num
* #return {number}
*/
function round(num) {
return num < 0 ? -Math.round(-num) : Math.round(num);
}
This seems to work correctly for these inputs:
round(-3) = -3
round(-2.9) = -3
round(-2.8) = -3
round(-2.7) = -3
round(-2.6) = -3
round(-2.5) = -3
round(-2.4) = -2
round(-2.3) = -2
round(-2.2) = -2
round(-2.1) = -2
round(-2) = -2
round(-1.9) = -2
round(-1.8) = -2
round(-1.7) = -2
round(-1.6) = -2
round(-1.5) = -2
round(-1.4) = -1
round(-1.3) = -1
round(-1.2) = -1
round(-1.1) = -1
round(-1) = -1
round(-0.9) = -1
round(-0.8) = -1
round(-0.7) = -1
round(-0.6) = -1
round(-0.5) = -1
round(-0.4) = 0
round(-0.3) = 0
round(-0.2) = 0
round(-0.1) = 0
round(0) = 0
round(0.1) = 0
round(0.2) = 0
round(0.3) = 0
round(0.4) = 0
round(0.5) = 1
round(0.6) = 1
round(0.7) = 1
round(0.8) = 1
round(0.9) = 1
round(1) = 1
round(1.1) = 1
round(1.2) = 1
round(1.3) = 1
round(1.4) = 1
round(1.5) = 2
round(1.6) = 2
round(1.7) = 2
round(1.8) = 2
round(1.9) = 2
round(2) = 2
round(2.1) = 2
round(2.2) = 2
round(2.3) = 2
round(2.4) = 2
round(2.5) = 3
round(2.6) = 3
round(2.7) = 3
round(2.8) = 3
round(2.9) = 3
round(3) = 3
I think negatives will always round to another negative or zero so this multiplication order is correct.

As #dandavis noted in the comments, the best way to handle this is to use .toFixed(2) instead of Math.round().
Math.round(), as you noted, rounds half up.
.toFixed() will round half away from zero. We designate the 2 in there to indicate the amount of decimals to use when doing the rounding.

Related

How to get numbers with precision without round up or round down [duplicate]

This question already has answers here:
Truncate (not round off) decimal numbers in javascript
(32 answers)
Closed 8 years ago.
Im trying to get a number with precision to 2 decimals, for example this is what I want, if I have the numbers:
3.456 it must returns me 3.45
3.467 = 3.46
3.435 = 3.43
3.422 = 3.42
I don't want to round up or down or whatever just to get the numbers I see 2 places after .
Thanks
Okay, here is the answer
var a = 5.469923;
var truncated = Math.floor(a * 100) / 100; // = 5.46
Thanks everyone for helping.
Assuming Positive Numbers:
The code:
function roundDown(num,dec) {
return Math.floor(num*Math.pow(10,dec))/Math.pow(10,dec);
}
The test:
function test(num, expected) {
var val = roundDown(num,2);
var pass = val === expected;
var result = pass ? "PASS" : "FAIL";
var color = pass ? "GREEN" : "RED";
console.log("%c" + result + " : " + num + " : " + val, "background-color:" + color);
}
test(3.456, 3.45);
test(3.467, 3.46);
test(3.435, 3.43);
test(3.422, 3.42);
Basic idea:
Take number
Multiply the number to move decimal place to number of significant figures you want
Floor the number to remove the trailing numbers
Divide number back to get the correct value
If you want to have a trailing zero, you need to use toFixed(2) which will turn the number to a string.
function roundDown(num,dec) {
return Math.floor(num*Math.pow(10,dec))/Math.pow(10,dec).toFixed(2);
}
and the test cases would need to change to
test(3.456, "3.45");
test(3.467, "3.46");
test(3.435, "3.43");
test(3.422, "3.42");
Another option is a regular expression.
function roundDown(num,dec) {
var x = num.toString().match(/(\d*(\.\d{2}))?/);
return x ? parseFloat(x[0]) : "";
//return x ? parseFloat(x[0]).toFixed(2) : "";
}
Use String operation to achieve it.
var n = 4.56789;
var numbers = n.toString().split('.');
result = Number(numbers[0]+"."+numbers[1].substr(0,2));
alert(result);
Fiddle
You are looking at the number as if it were a string of digits, rather than a single value, so treat it like a string.-
function cutoff(n, cut){
var parts= String(n).split('.'), dec= parts[1];
if(!cut) return parts[0];
if(dec && dec.length>cut) parts[1]= dec.substring(0, cut);
return parts.join('.');
}
var n= 36.938;
cutoff(n,2)
/* returned value: (String)
36.93
*/
If you want a number, +cutoff(n,2) will do.
function truncateDec(num, decplaces) {
return (num*Math.pow(10,decplaces) - num*Math.pow(10,decplaces) % 1)/Math.pow(10,decplaces);
}
alert(truncateDec(105.678, 2)); // Returns 105.67
alert(truncateDec(105.678, 1)); // Returns 105.6
This could be simplified further if you do not require a dynamic number of decimal places
function truncateDec(num) {
return (num*100 - num*100 % 1)/100;
}
alert(truncateDec(105.678)); // Returns 105.67
How does it work?
The concept is that the main truncation works by getting the remainder from dividing the original decimal by 1. The remainder will be whatever is in the decimals places. The remainder operator is %
105.678 % 1 = 0.678
By subtracting this remainder from the original number, we will be left with only the integer.
105.678 - 0.678 = 105
To include x number of decimal places, we need to first multiply the original number by 10 to the power of that number of decimal places, thereby shifting the decimal backward by x positions. In this example, we will take x = 2.
105.678 * 10^2
= 105.678 * 100
= 10567.8
Now, we repeat the same procedure by subtracting the remainder again.
10567.8 % 1 = 0.8
10567.8 - 0.8 = 10567
And to return back to the number of places as requested, we divide it back by 10^x
10567 / 10^2
= 10567 / 100
= 105.67
Hope it helps!

How to Generate a random number of fixed length using JavaScript?

I'm trying to generate a random number that must have a fixed length of exactly 6 digits.
I don't know if JavaScript has given below would ever create a number less than 6 digits?
Math.floor((Math.random()*1000000)+1);
I found this question and answer on StackOverflow here. But, it's unclear.
EDIT: I ran the above code a bunch of times, and Yes, it frequently creates numbers less than 6 digits. Is there a quick/fast way to make sure it's always exactly 6 digits?
console.log(Math.floor(100000 + Math.random() * 900000));
Will always create a number of 6 digits and it ensures the first digit will never be 0. The code in your question will create a number of less than 6 digits.
Only fully reliable answer that offers full randomness, without loss. The other ones prior to this answer all looses out depending on how many characters you want. The more you want, the more they lose randomness.
They achieve it by limiting the amount of numbers possible preceding the fixed length.
So for instance, a random number of fixed length 2 would be 10 - 99. For 3, 100 - 999. For 4, 1000 - 9999. For 5 10000 - 99999 and so on. As can be seen by the pattern, it suggests 10% loss of randomness because numbers prior to that are not possible. Why?
For really large numbers ( 18, 24, 48 ) 10% is still a lot of numbers to loose out on.
function generate(n) {
var add = 1, max = 12 - add; // 12 is the min safe number Math.random() can generate without it starting to pad the end with zeros.
if ( n > max ) {
return generate(max) + generate(n - max);
}
max = Math.pow(10, n+add);
var min = max/10; // Math.pow(10, n) basically
var number = Math.floor( Math.random() * (max - min + 1) ) + min;
return ("" + number).substring(add);
}
The generator allows for ~infinite length without lossy precision and with minimal performance cost.
Example:
generate(2)
"03"
generate(2)
"72"
generate(2)
"20"
generate(3)
"301"
generate(3)
"436"
generate(3)
"015"
As you can see, even the zero are included initially which is an additional 10% loss just that, besides the fact that numbers prior to 10^n are not possible.
That is now a total of 20%.
Also, the other options have an upper limit on how many characters you can actually generate.
Example with cost:
var start = new Date(); var num = generate(1000); console.log('Time: ', new Date() - start, 'ms for', num)
Logs:
Time: 0 ms for 7884381040581542028523049580942716270617684062141718855897876833390671831652069714762698108211737288889182869856548142946579393971303478191296939612816492205372814129483213770914444439430297923875275475120712223308258993696422444618241506074080831777597175223850085606310877065533844577763231043780302367695330451000357920496047212646138908106805663879875404784849990477942580056343258756712280958474020627842245866908290819748829427029211991533809630060693336825924167793796369987750553539230834216505824880709596544701685608502486365633618424746636614437646240783649056696052311741095247677377387232206206230001648953246132624571185908487227730250573902216708727944082363775298758556612347564746106354407311558683595834088577220946790036272364740219788470832285646664462382109714500242379237782088931632873392735450875490295512846026376692233811845787949465417190308589695423418373731970944293954443996348633968914665773009376928939207861596826457540403314327582156399232931348229798533882278769760
More hardcore:
generate(100000).length === 100000 -> true
I would go with this solution:
Math.floor(Math.random() * 899999 + 100000)
More generally, generating a random integer with fixed length can be done using Math.pow:
var randomFixedInteger = function (length) {
return Math.floor(Math.pow(10, length-1) + Math.random() * (Math.pow(10, length) - Math.pow(10, length-1) - 1));
}
To answer the question: randomFixedInteger(6);
You can use the below code to generate a random number that will always be 6 digits:
Math.random().toString().substr(2, 6)
Hope this works for everyone :)
Briefly how this works is Math.random() generates a random number between 0 and 1 which we convert to a string and using .toString() and take a 6 digit sample from said string using .substr() with the parameters 2, 6 to start the sample from the 2nd char and continue it for 6 characters.
This can be used for any length number.
If you want to do more reading on this here are some links to the docs to save you some googling:
Math.random(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
.toString(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
.substr(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr
short with arbitrary precision
below code ALWAYS generate string with n digits - solution in snippet use it
[...Array(n)].map(_=>Math.random()*10|0).join``
let gen = n=> [...Array(n)].map(_=>Math.random()*10|0).join``
// TEST: generate 6 digit number
// first number can't be zero - so we generate it separatley
let sixDigitStr = (1+Math.random()*9|0) + gen(5)
console.log( +(sixDigitStr) ) // + convert to num
100000 + Math.floor(Math.random() * 900000);
will give a number from 100000 to 999999 (inclusive).
Based on link you've provided, right answer should be
Math.floor(Math.random()*899999+100000);
Math.random() returns float between 0 and 1, so minimum number will be 100000, max - 999999. Exactly 6 digits, as you wanted :)
Here is my function I use. n - string length you want to generate
function generateRandomNumber(n) {
return Math.floor(Math.random() * (9 * Math.pow(10, n - 1))) + Math.pow(10, n - 1);
}
This is another random number generator that i use often, it also prevent the first digit from been zero(0)
function randomNumber(length) {
var text = "";
var possible = "123456789";
for (var i = 0; i < length; i++) {
var sup = Math.floor(Math.random() * possible.length);
text += i > 0 && sup == i ? "0" : possible.charAt(sup);
}
return Number(text);
}
let length = 6;
("0".repeat(length) + Math.floor(Math.random() * 10 ** length)).slice(-length);
Math.random() - Returns floating point number between 0 - 1
10 ** length - Multiply it by the length so we can get 1 - 6 length numbers with decimals
Math.floor() - Returns above number to integer(Largest integer to the given number).
What if we get less than 6 digits number?
That's why you have to append 0s with it.
"0".repeat() repeats the given string which is 0
So we may get more than 6 digits right?
That's why we have to use "".slice() method. It returns the array within given indexes. By giving minus values, it counts from the last element.
I created the below function to generate random number of fix length:
function getRandomNum(length) {
var randomNum =
(Math.pow(10,length).toString().slice(length-1) +
Math.floor((Math.random()*Math.pow(10,length))+1).toString()).slice(-length);
return randomNum;
}
This will basically add 0's at the beginning to make the length of the number as required.
npm install --save randomatic
var randomize = require('randomatic');
randomize(pattern, length, options);
Example:
To generate a 10-character randomized string using all available characters:
randomize('*', 10);
//=> 'x2_^-5_T[$'
randomize('Aa0!', 10);
//=> 'LV3u~BSGhw'
a: Lowercase alpha characters (abcdefghijklmnopqrstuvwxyz'
A: Uppercase alpha characters (ABCDEFGHIJKLMNOPQRSTUVWXYZ')
0: Numeric characters (0123456789')
!: Special characters (~!##$%^&()_+-={}[];\',.)
*: All characters (all of the above combined)
?: Custom characters (pass a string of custom characters to the options)
NPM repo
I use randojs to make the randomness simpler and more readable. you can pick a random int between 100000 and 999999 like this with randojs:
console.log(rando(100000, 999999));
<script src="https://randojs.com/1.0.0.js"></script>
const generate = n => String(Math.ceil(Math.random() * 10**n)).padStart(n, '0')
// n being the length of the random number.
Use a parseInt() or Number() on the result if you want an integer.
If you don't want the first integer to be a 0 then you could use padEnd() instead of padStart().
I was thinking about the same today and then go with the solution.
var generateOTP = function(otpLength=6) {
let baseNumber = Math.pow(10, otpLength -1 );
let number = Math.floor(Math.random()*baseNumber);
/*
Check if number have 0 as first digit
*/
if (number < baseNumber) {
number += baseNumber;
}
return number;
};
Let me know if it has any bug. Thanks.
"To Generate Random Number Using JS"
console.log(
Math.floor(Math.random() * 1000000)
);
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Math.random()</h2>
<p id="demo"></p>
</body>
</html>
You can use this module https://www.npmjs.com/package/uid, it generates variable length unique id
uid(10) => "hbswt489ts"
uid() => "rhvtfnt" Defaults to 7
Or you can have a look at this module https://www.npmjs.com/package/shortid
const shortid = require('shortid');
console.log(shortid.generate());
// PPBqWA9
Hope it works for you :)
var number = Math.floor(Math.random() * 9000000000) + 1000000000;
console.log(number);
This can be simplest way and reliable one.
For the length of 6, recursiveness doesn't matter a lot.
function random(len) {
let result = Math.floor(Math.random() * Math.pow(10, len));
return (result.toString().length < len) ? random(len) : result;
}
console.log(random(6));
In case you also want the first digit to be able to be 0 this is my solution:
const getRange = (size, start = 0) => Array(size).fill(0).map((_, i) => i + start);
const getRandomDigit = () => Math.floor(Math.random() * 10);
const generateVerificationCode = () => getRange(6).map(getRandomDigit).join('');
console.log(generateVerificationCode())
generate a random number that must have a fixed length of exactly 6 digits:
("000000"+Math.floor((Math.random()*1000000)+1)).slice(-6)
Generate a random number that will be 6 digits:
console.log(Math.floor(Math.random() * 900000));
Result = 500229
Generate a random number that will be 4 digits:
console.log(Math.floor(Math.random() * 9000));
Result = 8751
This code provides nearly full randomness:
function generator() {
const ran = () => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0].sort((x, z) => {
ren = Math.random();
if (ren == 0.5) return 0;
return ren > 0.5 ? 1 : -1
})
return Array(6).fill(null).map(x => ran()[(Math.random() * 9).toFixed()]).join('')
}
console.log(generator())
This code provides complete randomness:
function generator() {
const ran1 = () => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0].sort((x, z) => {
ren = Math.random();
if (ren == 0.5) return 0;
return ren > 0.5 ? 1 : -1
})
const ran2 = () => ran1().sort((x, z) => {
ren = Math.random();
if (ren == 0.5) return 0;
return ren > 0.5 ? 1 : -1
})
return Array(6).fill(null).map(x => ran2()[(Math.random() * 9).toFixed()]).join('')
}
console.log(generator())
parseInt(Math.random().toString().slice(2,Math.min(length+2, 18)), 10); // 18 -> due to max digits in Math.random
Update:
This method has few flaws:
- Sometimes the number of digits might be lesser if its left padded with zeroes.

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

Get decimal portion of a number with JavaScript

I have float numbers like 3.2 and 1.6.
I need to separate the number into the integer and decimal part. For example, a value of 3.2 would be split into two numbers, i.e. 3 and 0.2
Getting the integer portion is easy:
n = Math.floor(n);
But I am having trouble getting the decimal portion.
I have tried this:
remainder = n % 2; //obtem a parte decimal do rating
But it does not always work correctly.
The previous code has the following output:
n = 3.1 // gives remainder = 1.1
What I am missing here?
Use 1, not 2.
js> 2.3 % 1
0.2999999999999998
var decimal = n - Math.floor(n)
Although this won't work for minus numbers so we might have to do
n = Math.abs(n); // Change to positive
var decimal = n - Math.floor(n)
You could convert to string, right?
n = (n + "").split(".");
How is 0.2999999999999998 an acceptable answer? If I were the asker I would want an answer of .3. What we have here is false precision, and my experiments with floor, %, etc indicate that Javascript is fond of false precision for these operations. So I think the answers that are using conversion to string are on the right track.
I would do this:
var decPart = (n+"").split(".")[1];
Specifically, I was using 100233.1 and I wanted the answer ".1".
Here's how I do it, which I think is the most straightforward way to do it:
var x = 3.2;
int_part = Math.trunc(x); // returns 3
float_part = Number((x-int_part).toFixed(2)); // return 0.2
A simple way of doing it is:
var x = 3.2;
var decimals = x - Math.floor(x);
console.log(decimals); //Returns 0.20000000000000018
Unfortunately, that doesn't return the exact value. However, that is easily fixed:
var x = 3.2;
var decimals = x - Math.floor(x);
console.log(decimals.toFixed(1)); //Returns 0.2
You can use this if you don't know the number of decimal places:
var x = 3.2;
var decimals = x - Math.floor(x);
var decimalPlaces = x.toString().split('.')[1].length;
decimals = decimals.toFixed(decimalPlaces);
console.log(decimals); //Returns 0.2
Language independent way:
var a = 3.2;
var fract = a * 10 % 10 /10; //0.2
var integr = a - fract; //3
note that it correct only for numbers with one fractioanal lenght )
You can use parseInt() function to get the integer part than use that to extract the decimal part
var myNumber = 3.2;
var integerPart = parseInt(myNumber);
var decimalPart = myNumber - integerPart;
Or you could use regex like:
splitFloat = function(n){
const regex = /(\d*)[.,]{1}(\d*)/;
var m;
if ((m = regex.exec(n.toString())) !== null) {
return {
integer:parseInt(m[1]),
decimal:parseFloat(`0.${m[2]}`)
}
}
}
The following works regardless of the regional settings for decimal separator... on the condition only one character is used for a separator.
var n = 2015.15;
var integer = Math.floor(n).toString();
var strungNumber = n.toString();
if (integer.length === strungNumber.length)
return "0";
return strungNumber.substring(integer.length + 1);
It ain't pretty, but it's accurate.
If precision matters and you require consistent results, here are a few propositions that will return the decimal part of any number as a string, including the leading "0.". If you need it as a float, just add var f = parseFloat( result ) in the end.
If the decimal part equals zero, "0.0" will be returned. Null, NaN and undefined numbers are not tested.
1. String.split
var nstring = (n + ""),
narray = nstring.split("."),
result = "0." + ( narray.length > 1 ? narray[1] : "0" );
2. String.substring, String.indexOf
var nstring = (n + ""),
nindex = nstring.indexOf("."),
result = "0." + (nindex > -1 ? nstring.substring(nindex + 1) : "0");
3. Math.floor, Number.toFixed, String.indexOf
var nstring = (n + ""),
nindex = nstring.indexOf("."),
result = ( nindex > -1 ? (n - Math.floor(n)).toFixed(nstring.length - nindex - 1) : "0.0");
4. Math.floor, Number.toFixed, String.split
var nstring = (n + ""),
narray = nstring.split("."),
result = (narray.length > 1 ? (n - Math.floor(n)).toFixed(narray[1].length) : "0.0");
Here is a jsPerf link: https://jsperf.com/decpart-of-number/
We can see that proposition #2 is the fastest.
A good option is to transform the number into a string and then split it.
// Decimal number
let number = 3.2;
// Convert it into a string
let string = number.toString();
// Split the dot
let array = string.split('.');
// Get both numbers
// The '+' sign transforms the string into a number again
let firstNumber = +array[0]; // 3
let secondNumber = +array[1]; // 2
In one line of code
let [firstNumber, secondNumber] = [+number.toString().split('.')[0], +number.toString().split('.')[1]];
Depending the usage you will give afterwards, but this simple solution could also help you.
Im not saying its a good solution, but for some concrete cases works
var a = 10.2
var c = a.toString().split(".")
console.log(c[1] == 2) //True
console.log(c[1] === 2) //False
But it will take longer than the proposed solution by #Brian M. Hunt
(2.3 % 1).toFixed(4)
I am using:
var n = -556.123444444;
var str = n.toString();
var decimalOnly = 0;
if( str.indexOf('.') != -1 ){ //check if has decimal
var decimalOnly = parseFloat(Math.abs(n).toString().split('.')[1]);
}
Input: -556.123444444
Result: 123444444
You could convert it to a string and use the replace method to replace the integer part with zero, then convert the result back to a number :
var number = 123.123812,
decimals = +number.toString().replace(/^[^\.]+/,'0');
n = Math.floor(x);
remainder = x % 1;
Math functions are faster, but always returns not native expected values.
Easiest way that i found is
(3.2+'').replace(/^[-\d]+\./, '')
The best way to avoid mathematical imprecision is to convert to a string, but ensure that it is in the "dot" format you expect by using toLocaleString:
function getDecimals(n) {
// Note that maximumSignificantDigits defaults to 3 so your decimals will be rounded if not changed.
const parts = n.toLocaleString('en-US', { maximumSignificantDigits: 18 }).split('.')
return parts.length > 1 ? Number('0.' + parts[1]) : 0
}
console.log(getDecimals(10.58))
You can simply use parseInt() function to help, example:
let decimal = 3.2;
let remainder = decimal - parseInt(decimal);
document.write(remainder);
I had a case where I knew all the numbers in question would have only one decimal and wanted to get the decimal portion as an integer so I ended up using this kind of approach:
var number = 3.1,
decimalAsInt = Math.round((number - parseInt(number)) * 10); // returns 1
This works nicely also with integers, returning 0 in those cases.
Although I am very late to answer this, please have a look at the code.
let floatValue = 3.267848;
let decimalDigits = floatValue.toString().split('.')[1];
let decimalPlaces = decimalDigits.length;
let decimalDivider = Math.pow(10, decimalPlaces);
let fractionValue = decimalDigits/decimalDivider;
let integerValue = floatValue - fractionValue;
console.log("Float value: "+floatValue);
console.log("Integer value: "+integerValue);
console.log("Fraction value: "+fractionValue)
I like this answer https://stackoverflow.com/a/4512317/1818723 just need to apply float point fix
function fpFix(n) {
return Math.round(n * 100000000) / 100000000;
}
let decimalPart = 2.3 % 1; //0.2999999999999998
let correct = fpFix(decimalPart); //0.3
Complete function handling negative and positive
function getDecimalPart(decNum) {
return Math.round((decNum % 1) * 100000000) / 100000000;
}
console.log(getDecimalPart(2.3)); // 0.3
console.log(getDecimalPart(-2.3)); // -0.3
console.log(getDecimalPart(2.17247436)); // 0.17247436
P.S. If you are cryptocurrency trading platform developer or banking system developer or any JS developer ;) please apply fpFix everywhere. Thanks!
2021 Update
Optimized version that tackles precision (or not).
// Global variables.
const DEFAULT_PRECISION = 16;
const MAX_CACHED_PRECISION = 20;
// Helper function to avoid numerical imprecision from Math.pow(10, x).
const _pow10 = p => parseFloat(`1e+${p}`);
// Cache precision coefficients, up to a precision of 20 decimal digits.
const PRECISION_COEFS = new Array(MAX_CACHED_PRECISION);
for (let i = 0; i !== MAX_CACHED_PRECISION; ++i) {
PRECISION_COEFS[i] = _pow10(i);
}
// Function to get a power of 10 coefficient,
// optimized for both speed and precision.
const pow10 = p => PRECISION_COEFS[p] || _pow10(p);
// Function to trunc a positive number, optimized for speed.
// See: https://stackoverflow.com/questions/38702724/math-floor-vs-math-trunc-javascript
const trunc = v => (v < 1e8 && ~~v) || Math.trunc(v);
// Helper function to get the decimal part when the number is positive,
// optimized for speed.
// Note: caching 1 / c or 1e-precision still leads to numerical errors.
// So we have to pay the price of the division by c.
const _getDecimals = (v = 0, precision = DEFAULT_PRECISION) => {
const c = pow10(precision); // Get precision coef.
const i = trunc(v); // Get integer.
const d = v - i; // Get decimal.
return Math.round(d * c) / c;
}
// Augmenting Number proto.
Number.prototype.getDecimals = function(precision) {
return (isFinite(this) && (precision ? (
(this < 0 && -_getDecimals(-this, precision))
|| _getDecimals(this, precision)
) : this % 1)) || 0;
}
// Independent function.
const getDecimals = (input, precision) => (isFinite(input) && (
precision ? (
(this < 0 && -_getDecimals(-this, precision))
|| _getDecimals(this, precision)
) : this % 1
)) || 0;
// Tests:
const test = (value, precision) => (
console.log(value, '|', precision, '-->', value.getDecimals(precision))
);
test(1.001 % 1); // --> 0.0009999999999998899
test(1.001 % 1, 16); // --> 0.000999999999999
test(1.001 % 1, 15); // --> 0.001
test(1.001 % 1, 3); // --> 0.001
test(1.001 % 1, 2); // --> 0
test(-1.001 % 1, 16); // --> -0.000999999999999
test(-1.001 % 1, 15); // --> -0.001
test(-1.001 % 1, 3); // --> -0.001
test(-1.001 % 1, 2); // --> 0
After looking at several of these, I am now using...
var rtnValue = Number(7.23);
var tempDec = ((rtnValue / 1) - Math.floor(rtnValue)).toFixed(2);
Floating-point decimal sign and number format can be dependent from country (.,), so independent solution, which preserved floating point part, is:
getFloatDecimalPortion = function(x) {
x = Math.abs(parseFloat(x));
let n = parseInt(x);
return Number((x - n).toFixed(Math.abs((""+x).length - (""+n).length - 1)));
}
– it is internationalized solution, instead of location-dependent:
getFloatDecimalPortion = x => parseFloat("0." + ((x + "").split(".")[1]));
Solution desription step by step:
parseFloat() for guaranteeing input cocrrection
Math.abs() for avoiding problems with negative numbers
n = parseInt(x) for getting decimal part
x - n for substracting decimal part
We have now number with zero decimal part, but JavaScript could give us additional floating part digits, which we do not want
So, limit additional digits by calling toFixed() with count of digits in floating part of original float number x. Count is calculated as difference between length of original number x and number n in their string representation.
This function splits float number into integers and returns it in array:
function splitNumber(num)
{
num = (""+num).match(/^(-?[0-9]+)([,.][0-9]+)?/)||[];
return [ ~~num[1], +(0+num[2])||0 ];
}
console.log(splitNumber(3.02)); // [ 3, 0.2 ]
console.log(splitNumber(123.456)); // [ 123, 0.456 ]
console.log(splitNumber(789)); // [ 789, 0 ]
console.log(splitNumber(-2.7)); // [ -2, 0.7 ]
console.log(splitNumber("test")); // [ 0, 0 ]
You can extend it to only return existing numbers and null if no number exists:
function splitNumber(num)
{
num = (""+num).match(/^(-?[0-9]+)([,.][0-9]+)?/);
return [ num ? ~~num[1] : null, num && num[2] ? +(0 + num[2]) : null ];
}
console.log(splitNumber(3.02)); // [ 3, 0.02 ]
console.log(splitNumber(123.456)); // [ 123, 0.456 ]
console.log(splitNumber(789)); // [ 789, null ]
console.log(splitNumber(-2.7)); // [ -2, 0.7 ]
console.log(splitNumber("test")); // [ null, null ]
You can also truncate the number
function decimals(val) {
const valStr = val.toString();
const valTruncLength = String(Math.trunc(val)).length;
const dec =
valStr.length != valTruncLength
? valStr.substring(valTruncLength + 1)
: "";
return dec;
}
console.log("decimals: ", decimals(123.654321));
console.log("no decimals: ", decimals(123));
The following function will return an array which will have 2 elements. The first element will be the integer part and the second element will be the decimal part.
function splitNum(num) {
num = num.toString().split('.')
num[0] = Number(num[0])
if (num[1]) num[1] = Number('0.' + num[1])
else num[1] = 0
return num
}
//call this function like this
let num = splitNum(3.2)
console.log(`Integer part is ${num[0]}`)
console.log(`Decimal part is ${num[1]}`)
//or you can call it like this
let [int, deci] = splitNum(3.2)
console.log('Intiger part is ' + int)
console.log('Decimal part is ' + deci)
For example for add two numbers
function add(number1, number2) {
let decimal1 = String(number1).substring(String(number1).indexOf(".") + 1).length;
let decimal2 = String(number2).substring(String(number2).indexOf(".") + 1).length;
let z = Math.max(decimal1, decimal2);
return (number1 * Math.pow(10, z) + number2 * Math.pow(10, z)) / Math.pow(10, z);
}
float a=3.2;
int b=(int)a; // you'll get output b=3 here;
int c=(int)a-b; // you'll get c=.2 value here

How to perform an integer division, and separately get the remainder, in JavaScript?

In JavaScript, how do I get:
The whole number of times a given integer goes into another?
The remainder?
For some number y and some divisor x compute the quotient (quotient)[1] and remainder (remainder) as:
const quotient = Math.floor(y/x);
const remainder = y % x;
Example:
const quotient = Math.floor(13/3); // => 4 => the times 3 fits into 13
const remainder = 13 % 3; // => 1
[1] The integer number resulting from the division of one number by another
I'm no expert in bitwise operators, but here's another way to get the whole number:
var num = ~~(a / b);
This will work properly for negative numbers as well, while Math.floor() will round in the wrong direction.
This seems correct as well:
var num = (a / b) >> 0;
I did some speed tests on Firefox.
-100/3 // -33.33..., 0.3663 millisec
Math.floor(-100/3) // -34, 0.5016 millisec
~~(-100/3) // -33, 0.3619 millisec
(-100/3>>0) // -33, 0.3632 millisec
(-100/3|0) // -33, 0.3856 millisec
(-100-(-100%3))/3 // -33, 0.3591 millisec
/* a=-100, b=3 */
a/b // -33.33..., 0.4863 millisec
Math.floor(a/b) // -34, 0.6019 millisec
~~(a/b) // -33, 0.5148 millisec
(a/b>>0) // -33, 0.5048 millisec
(a/b|0) // -33, 0.5078 millisec
(a-(a%b))/b // -33, 0.6649 millisec
The above is based on 10 million trials for each.
Conclusion: Use (a/b>>0) (or (~~(a/b)) or (a/b|0)) to achieve about 20% gain in efficiency. Also keep in mind that they are all inconsistent with Math.floor, when a/b<0 && a%b!=0.
ES6 introduces the new Math.trunc method. This allows to fix #MarkElliot's answer to make it work for negative numbers too:
var div = Math.trunc(y/x);
var rem = y % x;
Note that Math methods have the advantage over bitwise operators that they work with numbers over 231.
I normally use:
const quotient = (a - a % b) / b;
const remainder = a % b;
It's probably not the most elegant, but it works.
var remainder = x % y;
return (x - remainder) / y;
You can use the function parseInt to get a truncated result.
parseInt(a/b)
To get a remainder, use mod operator:
a%b
parseInt have some pitfalls with strings, to avoid use radix parameter with base 10
parseInt("09", 10)
In some cases the string representation of the number can be a scientific notation, in this case, parseInt will produce a wrong result.
parseInt(100000000000000000000000000000000, 10) // 1e+32
This call will produce 1 as result.
Math.floor(operation) returns the rounded down value of the operation.
Example of 1st question:
const x = 5;
const y = 10.4;
const z = Math.floor(x + y);
console.log(z);
Example of 2nd question:
const x = 14;
const y = 5;
const z = Math.floor(x % y);
console.log(x);
JavaScript calculates right the floor of negative numbers and the remainder of non-integer numbers, following the mathematical definitions for them.
FLOOR is defined as "the largest integer number smaller than the parameter", thus:
positive numbers: FLOOR(X)=integer part of X;
negative numbers: FLOOR(X)=integer part of X minus 1 (because it must be SMALLER than the parameter, i.e., more negative!)
REMAINDER is defined as the "left over" of a division (Euclidean arithmetic). When the dividend is not an integer, the quotient is usually also not an integer, i.e., there is no remainder, but if the quotient is forced to be an integer (and that's what happens when someone tries to get the remainder or modulus of a floating-point number), there will be a non-integer "left over", obviously.
JavaScript does calculate everything as expected, so the programmer must be careful to ask the proper questions (and people should be careful to answer what is asked!) Yarin's first question was NOT "what is the integer division of X by Y", but, instead, "the WHOLE number of times a given integer GOES INTO another". For positive numbers, the answer is the same for both, but not for negative numbers, because the integer division (dividend by divisor) will be -1 smaller than the times a number (divisor) "goes into" another (dividend). In other words, FLOOR will return the correct answer for an integer division of a negative number, but Yarin didn't ask that!
gammax answered correctly, that code works as asked by Yarin. On the other hand, Samuel is wrong, he didn't do the maths, I guess, or he would have seen that it does work (also, he didn't say what was the divisor of his example, but I hope it was 3):
Remainder = X % Y = -100 % 3 = -1
GoesInto = (X - Remainder) / Y = (-100 - -1) / 3 = -99 / 3 = -33
By the way, I tested the code on Firefox 27.0.1, it worked as expected, with positive and negative numbers and also with non-integer values, both for dividend and divisor. Example:
-100.34 / 3.57: GoesInto = -28, Remainder = -0.3800000000000079
Yes, I noticed, there is a precision problem there, but I didn't had time to check it (I don't know if it's a problem with Firefox, Windows 7 or with my CPU's FPU). For Yarin's question, though, which only involves integers, the gammax's code works perfectly.
const idivmod = (a, b) => [a/b |0, a%b];
there is also a proposal working on it
Modulus and Additional Integer Math
Alex Moore-Niemi's comment as an answer:
For Rubyists here from Google in search of divmod, you can implement it as such:
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
Result:
// [2, 33]
If you need to calculate the remainder for very large integers, which the JS runtime cannot represent as such (any integer greater than 2^32 is represented as a float and so it loses precision), you need to do some trick.
This is especially important for checking many case of check digits which are present in many instances of our daily life (bank account numbers, credit cards, ...)
First of all you need your number as a string (otherwise you have already lost precision and the remainder does not make sense).
str = '123456789123456789123456789'
You now need to split your string in smaller parts, small enough so the concatenation of any remainder and a piece of string can fit in 9 digits.
digits = 9 - String(divisor).length
Prepare a regular expression to split the string
splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')
For instance, if digits is 7, the regexp is
/.{1,7}(?=(.{7})+$)/g
It matches a nonempty substring of maximum length 7, which is followed ((?=...) is a positive lookahead) by a number of characters that is multiple of 7. The 'g' is to make the expression run through all string, not stopping at first match.
Now convert each part to integer, and calculate the remainders by reduce (adding back the previous remainder - or 0 - multiplied by the correct power of 10):
reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor
This will work because of the "subtraction" remainder algorithm:
n mod d = (n - kd) mod d
which allows to replace any 'initial part' of the decimal representation of a number with its remainder, without affecting the final remainder.
The final code would look like:
function remainder(num, div) {
const digits = 9 - String(div).length;
const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
const mult = Math.pow(10, digits);
const reducer = (rem, piece) => (rem * mult + piece) % div;
return str.match(splitter).map(Number).reduce(reducer, 0);
}
If you are just dividing with powers of two, you can use bitwise operators:
export function divideBy2(num) {
return [num >> 1, num & 1];
}
export function divideBy4(num) {
return [num >> 2, num & 3];
}
export function divideBy8(num) {
return [num >> 3, num & 7];
}
(The first is the quotient, the second the remainder)
function integerDivison(dividend, divisor){
this.Division = dividend/divisor;
this.Quotient = Math.floor(dividend/divisor);
this.Remainder = dividend%divisor;
this.calculate = ()=>{
return {Value:this.Division,Quotient:this.Quotient,Remainder:this.Remainder};
}
}
var divide = new integerDivison(5,2);
console.log(divide.Quotient) //to get Quotient of two value
console.log(divide.division) //to get Floating division of two value
console.log(divide.Remainder) //to get Remainder of two value
console.log(divide.calculate()) //to get object containing all the values
You can use ternary to decide how to handle positive and negative integer values as well.
var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1
If the number is a positive, all is fine. If the number is a negative, it will add 1 because of how Math.floor handles negatives.
This will always truncate towards zero.
Not sure if it is too late, but here it goes:
function intdiv(dividend, divisor) {
divisor = divisor - divisor % 1;
if (divisor == 0) throw new Error("division by zero");
dividend = dividend - dividend % 1;
var rem = dividend % divisor;
return {
remainder: rem,
quotient: (dividend - rem) / divisor
};
}
Calculating number of pages may be done in one step:
Math.ceil(x/y)
Here is a way to do this. (Personally I would not do it this way, but thought it was a fun way to do it for an example) The ways mentioned above are definitely better as this calls multiple functions and is therefore slower as well as takes up more room in your bundle.
function intDivide(numerator, denominator) {
return parseInt((numerator/denominator).toString().split(".")[0]);
}
let x = intDivide(4,5);
let y = intDivide(5,5);
let z = intDivide(6,5);
console.log(x);
console.log(y);
console.log(z);

Categories

Resources