Round float value with 6 not 5 - javascript

I need some help on this, I have a big float value (Ex.: 18.235555).
In some countries, rounding up begins from 6, and not from 5.
I know use only 2 decimal, but I need something different:
18.235555 = 18.24
but this
18.23666 = 18.24
$('#val').html( Number(Math.round(1.005+'e2')+'e-2' ) );
Example: now I have this [https://jsfiddle.net/tevez15/ywm8bonp/][1]
var n = 1.665;
(Math.round( n * 100 )/100 ).toString()
Solution: [1]: https://jsfiddle.net/tevez15/ywm8bonp/

Since it is possible again to answer I'd like to formulate my solution in a proper way.
Your way to round numbers can be archieved by the following code:
var myRounding = function(value, decimalplaces) {
var decFac = decimalFactor(decimalplaces);
var facVal = value * decFac;
if(facVal - Math.floor(facVal) < 0.6) {
return Math.floor(facVal) / decFac;
}
return Math.ceil(facVal) / decFac;
}
var decimalFactor = function(decimalplaces) {
if(!decimalplaces)
decimalplaces = 0;
return Math.pow(10,decimalplaces);
}

Related

Javascript format a decimal number to tree numbers after decimal

How can I format numbers like
0.00012006 to 0.00012
0.00004494 to 0.0000449
0.000000022732 to 0.0000000227 without becoming a number like 2.3e-8
I would like to know how I can change numbers like that in a fast/efficient way.
I would like to know how to convert those numbers but if someone knows how to format it only like that, I would like to know that too.
Use yourNumber.toFixed(numberOfDigitsAfterDot) like this:
function format(n) {
var _n = n;
// count the position of the first decimal
var count = 0;
do {
n = n * 10;
count++;
} while(n < 1);
return _n.toFixed(count + 2);
}
var num = 0.000000022732;
console.log(format(num));
You coud get the places of the number and add 2 on it for toFixed.
function three(v) {
var n = Math.floor(Math.log(v) / Math.LN10);
return v.toFixed(n < 2 ? 2 - n : 0);
}
var n = [0.00012006, 0.00004494, 0.000000022732, 0.100101, 0.1100001, 1.000001, 12000, 10, 1e10];
console.log(n.map(three));

javascript toFixed()

In many case toFixed() fail cause of floating point in javascript math.
I found this solution:
function toFixed(decimalPlaces) {
var factor = Math.pow(10, decimalPlaces || 0);
var v = (Math.round(Math.round(this * factor * 100) / 100) / factor).toString();
if (v.indexOf('.') >= 0) {
return v + factor.toString().substr(v.length - v.indexOf('.'));
}
return v + '.' + factor.toString().substr(1);
}
and this:
function toFixed(num, fixed) {
var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
return num.toString().match(re)[0];
}
There are other approaches? I have to be certain that performs well in any case. Also in borderline-cases.
EDIT:
https://github.com/MikeMcl/decimal.js
#Tschallacka
Number.prototype.toFixed = function(fixed) {
x = new Decimal(Number(this));
return x.toFixed(fixed);
};
I suggest you use a library:
https://github.com/MikeMcl/decimal.js
I found it very dependable when working with finanical data.
Working with floating point numbers is always difficult, but there are several solutions out there.
I suggest you use an existin library that is well maintained, which already has had it's baby teeth knocked out.
Assuming you added decimal.js you can do this for financial values.
/**
* #var input float
*/
function toFixed(input) {
var dec = new Decimal(input);
return dec.toFixed(2);
}
console.log("float to fixed 2 decimal places: ",toFixed(200.23546546546));
function toFixed2(decimalPlaces) {
var dec = new Decimal(1);
return dec.toFixed(decimalPlaces);
}
console.log("get a fixed num: ",toFixed2(10));
Number.prototype.toFixed = function(fixed) {
x = new Decimal(Number(this));
return x.toFixed(fixed);
};
var num = new Number(10.4458);
console.log("Number to fixed via prototyped method: ",num.toFixed(2));
var x = 44.456
console.log('Number to fixed via inderect number casting:' ,x.toFixed(2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/decimal.js/7.1.1/decimal.min.js"></script>

Javascript rounding failure

This is the rounding function we are using (which is taken from stackoverflow answers on how to round). It rounds half up to 2dp (by default)
e.g. 2.185 should go to 2.19
function myRound(num, places) {
if (places== undefined) {
// default to 2dp
return Math.round(num* 100) / 100;
}
var mult = Math.pow(10,places);
return Math.round(num* mult) / mult;
}
It has worked well but now we have found some errors in it (in both chrome and running as jscript classic asp on IIS 7.5).
E.g.:
alert(myRound(2.185)); // = 2.19
alert (myRound(122.185)); // = 122.19
alert (myRound(511.185)); // = 511.19
alert (myRound(522.185)); // = 522.18 FAIL!!!!
alert (myRound(625.185)); // = 625.18 FAIL!!!!
Does anyone know:
Why this happens.
How we can round half up to 2 dp without random rounding errors like this.
update: OK, the crux of the problem is that in js, 625.185 * 100 = 62518.499999
How can we get over this?
Your problem is not easily resolved. It occurs because IEEE doubles use a binary representation that cannot exactly represent all decimals. The closest internal representation to 625.185 is 625.18499999999994543031789362430572509765625, which is ever so slightly less than 625.185, and for which the correct rounding is downwards.
Depending on your circumstances, you might get away with the following:
Math.round(Math.round(625.185 * 1000) / 10) / 100 // evaluates to 625.19
This isn't strictly correct, however, since, e.g., it will round, 625.1847 upwards to 625.19. Only use it if you know that the input will never have more than three decimal places.
A simpler option is to add a small epsilon before rounding:
Math.round(625.185 * 100 + 1e-6) / 100
This is still a compromise, since you might conceivably have a number that is very slightly less than 625.185, but it's probably more robust than the first solution. Watch out for negative numbers, though.
Try using toFixed function on value.
example is below:
var value = parseFloat(2.185);
var fixed = value.toFixed(2);
alert(fixed);
I tried and it worked well.
EDIT: You can always transform string to number using parseFloat(stringVar).
EDIT2:
function myRound(num, places) {
return parseFloat(num.toFixed(places));
}
EDIT 3:
Updated answer, tested and working:
function myRound(num, places) {
if (places== undefined) {
places = 2;
}
var mult = Math.pow(10,places + 1);
var mult2 = Math.pow(10,places);
return Math.round(num* mult / 10) / mult2;
}
EDIT 4:
Tested on most examples noted in comments:
function myRound(num, places) {
if (places== undefined) {
places = 2;
}
var mult = Math.pow(10,places);
var val = num* mult;
var intVal = parseInt(val);
var floatVal = parseFloat(val);
if (intVal < floatVal) {
val += 0.1;
}
return Math.round(val) / mult;
}
EDIT 5:
Only solution that I managed to find is to use strings to get round on exact decimal.
Solution is pasted below, with String prototype extension method, replaceAt.
Please check and let me know if anyone finds some example that is not working.
function myRound2(num, places) {
var retVal = null;
if (places == undefined) {
places = 2;
}
var splits = num.split('.');
if (splits && splits.length <= 2) {
var wholePart = splits[0];
var decimalPart = null;
if (splits.length > 1) {
decimalPart = splits[1];
}
if (decimalPart && decimalPart.length > places) {
var roundingDigit = parseInt(decimalPart[places]);
var previousDigit = parseInt(decimalPart[places - 1]);
var increment = (roundingDigit < 5) ? 0 : 1;
previousDigit = previousDigit + increment;
decimalPart = decimalPart.replaceAt(places - 1, previousDigit + '').substr(0, places);
}
retVal = parseFloat(wholePart + '.' + decimalPart);
}
return retVal;
}
String.prototype.replaceAt = function (index, character) {
return this.substr(0, index) + character + this.substr(index + character.length);
}
OK, found a "complete" solution to the issue.
Firstly, donwnloaded Big.js from here: https://github.com/MikeMcl/big.js/
Then modified the source so it would work with jscript/asp:
/* big.js v2.1.0 https://github.com/MikeMcl/big.js/LICENCE */
var Big = (function ( global ) {
'use strict';
:
// EXPORT
return Big;
})( this );
Then did my calculation using Big types and used the Big toFixed(dp), then converted back into a number thusly:
var bigMult = new Big (multiplier);
var bigLineStake = new Big(lineStake);
var bigWin = bigLineStake.times(bigMult);
var strWin = bigWin.toFixed(2); // this does the rounding correctly.
var win = parseFloat(strWin); // back to a number!
This basically uses Bigs own rounding in its toFixed, which seems to work correctly in all cases.
Shame Big doesnt have a method to convert back to a number without having to go through a string.

Truncate (not round off) decimal numbers in javascript

I am trying to truncate decimal numbers to decimal places. Something like this:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2) does just about the right thing but it rounds off the value. I don't need the value rounded off. Hope this is possible in javascript.
Dogbert's answer is good, but if your code might have to deal with negative numbers, Math.floor by itself may give unexpected results.
E.g. Math.floor(4.3) = 4, but Math.floor(-4.3) = -5
Use a helper function like this one instead to get consistent results:
truncateDecimals = function (number) {
return Math[number < 0 ? 'ceil' : 'floor'](number);
};
// Applied to Dogbert's answer:
var a = 5.467;
var truncated = truncateDecimals(a * 100) / 100; // = 5.46
Here's a more convenient version of this function:
truncateDecimals = function (number, digits) {
var multiplier = Math.pow(10, digits),
adjustedNum = number * multiplier,
truncatedNum = Math[adjustedNum < 0 ? 'ceil' : 'floor'](adjustedNum);
return truncatedNum / multiplier;
};
// Usage:
var a = 5.467;
var truncated = truncateDecimals(a, 2); // = 5.46
// Negative digits:
var b = 4235.24;
var truncated = truncateDecimals(b, -2); // = 4200
If that isn't desired behaviour, insert a call to Math.abs on the first line:
var multiplier = Math.pow(10, Math.abs(digits)),
EDIT: shendz correctly points out that using this solution with a = 17.56 will incorrectly produce 17.55. For more about why this happens, read What Every Computer Scientist Should Know About Floating-Point Arithmetic. Unfortunately, writing a solution that eliminates all sources of floating-point error is pretty tricky with javascript. In another language you'd use integers or maybe a Decimal type, but with javascript...
This solution should be 100% accurate, but it will also be slower:
function truncateDecimals (num, digits) {
var numS = num.toString(),
decPos = numS.indexOf('.'),
substrLength = decPos == -1 ? numS.length : 1 + decPos + digits,
trimmedResult = numS.substr(0, substrLength),
finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;
return parseFloat(finalResult);
}
For those who need speed but also want to avoid floating-point errors, try something like BigDecimal.js. You can find other javascript BigDecimal libraries in this SO question: "Is there a good Javascript BigDecimal library?" and here's a good blog post about math libraries for Javascript
upd:
So, after all it turned out, rounding bugs will always haunt you, no matter how hard you try to compensate them. Hence the problem should be attacked by representing numbers exactly in decimal notation.
Number.prototype.toFixedDown = function(digits) {
var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
m = this.toString().match(re);
return m ? parseFloat(m[1]) : this.valueOf();
};
[ 5.467.toFixedDown(2),
985.943.toFixedDown(2),
17.56.toFixedDown(2),
(0).toFixedDown(1),
1.11.toFixedDown(1) + 22];
// [5.46, 985.94, 17.56, 0, 23.1]
Old error-prone solution based on compilation of others':
Number.prototype.toFixedDown = function(digits) {
var n = this - Math.pow(10, -digits)/2;
n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56"
return n.toFixed(digits);
}
var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46
You can fix the rounding by subtracting 0.5 for toFixed, e.g.
(f - 0.005).toFixed(2)
Nice one-line solution:
function truncate (num, places) {
return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places);
}
Then call it with:
truncate(3.5636232, 2); // returns 3.56
truncate(5.4332312, 3); // returns 5.433
truncate(25.463214, 4); // returns 25.4632
Consider taking advantage of the double tilde: ~~.
Take in the number. Multiply by significant digits after the decimal so that you can truncate to zero places with ~~. Divide that multiplier back out. Profit.
function truncator(numToTruncate, intDecimalPlaces) {
var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
return ~~(numToTruncate * numPower)/numPower;
}
I'm trying to resist wrapping the ~~ call in parens; order of operations should make that work correctly, I believe.
alert(truncator(5.1231231, 1)); // is 5.1
alert(truncator(-5.73, 1)); // is -5.7
alert(truncator(-5.73, 0)); // is -5
JSFiddle link.
EDIT: Looking back over, I've unintentionally also handled cases to round off left of the decimal as well.
alert(truncator(4343.123, -2)); // gives 4300.
The logic's a little wacky looking for that usage, and may benefit from a quick refactor. But it still works. Better lucky than good.
I thought I'd throw in an answer using | since it is simple and works well.
truncate = function(number, places) {
var shift = Math.pow(10, places);
return ((number * shift) | 0) / shift;
};
Truncate using bitwise operators:
~~0.5 === 0
~~(-0.5) === 0
~~14.32794823 === 14
~~(-439.93) === -439
#Dogbert's answer can be improved with Math.trunc, which truncates instead of rounding.
There is a difference between rounding and truncating. Truncating is
clearly the behaviour this question is seeking. If I call
truncate(-3.14) and receive -4 back, I would definitely call that
undesirable. – #NickKnowlson
var a = 5.467;
var truncated = Math.trunc(a * 100) / 100; // = 5.46
var a = -5.467;
var truncated = Math.trunc(a * 100) / 100; // = -5.46
I wrote an answer using a shorter method. Here is what I came up with
function truncate(value, precision) {
var step = Math.pow(10, precision || 0);
var temp = Math.trunc(step * value);
return temp / step;
}
The method can be used like so
truncate(132456.25456789, 5)); // Output: 132456.25456
truncate(132456.25456789, 3)); // Output: 132456.254
truncate(132456.25456789, 1)); // Output: 132456.2
truncate(132456.25456789)); // Output: 132456
Or, if you want a shorter syntax, here you go
function truncate(v, p) {
var s = Math.pow(10, p || 0);
return Math.trunc(s * v) / s;
}
I think this function could be a simple solution:
function trunc(decimal,n=2){
let x = decimal + ''; // string
return x.lastIndexOf('.')>=0?parseFloat(x.substr(0,x.lastIndexOf('.')+(n+1))):decimal; // You can use indexOf() instead of lastIndexOf()
}
console.log(trunc(-241.31234,2));
console.log(trunc(241.312,5));
console.log(trunc(-241.233));
console.log(trunc(241.2,0));
console.log(trunc(241));
Number.prototype.trim = function(decimals) {
var s = this.toString();
var d = s.split(".");
d[1] = d[1].substring(0, decimals);
return parseFloat(d.join("."));
}
console.log((5.676).trim(2)); //logs 5.67
I'm a bit confused as to why there are so many different answers to such a fundamentally simple question; there are only two approaches which I saw which seemed to be worth looking at. I did a quick benchmark to see the speed difference using https://jsbench.me/.
This is the solution which is currently (9/26/2020) flagged as the answer:
function truncate(n, digits) {
var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
m = n.toString().match(re);
return m ? parseFloat(m[1]) : n.valueOf();
};
[ truncate(5.467,2),
truncate(985.943,2),
truncate(17.56,2),
truncate(0, 1),
truncate(1.11, 1) + 22];
However, this is doing string and regex stuff, which is usually not very efficient, and there is a Math.trunc function which does exactly what the OP wants just with no decimals. Therefore, you can easily use that plus a little extra arithmetic to get the same thing.
Here is another solution I found on this thread, which is the one I would use:
function truncate(n, digits) {
var step = Math.pow(10, digits || 0);
var temp = Math.trunc(step * n);
return temp / step;
}
[ truncate(5.467,2),
truncate(985.943,2),
truncate(17.56,2),
truncate(0, 1),
truncate(1.11, 1) + 22];
The first method is "99.92% slower" than the second, so the second is definitely the one I would recommend using.
Okay, back to finding other ways to avoid work...
I found a problem: considering the next situation: 2.1 or 1.2 or -6.4
What if you want always 3 decimals or two or wharever, so, you have to complete the leading zeros to the right
// 3 decimals numbers
0.5 => 0.500
// 6 decimals
0.1 => 0.10000
// 4 decimales
-2.1 => -2.1000
// truncate to 3 decimals
3.11568 => 3.115
This is the fixed function of Nick Knowlson
function truncateDecimals (num, digits)
{
var numS = num.toString();
var decPos = numS.indexOf('.');
var substrLength = decPos == -1 ? numS.length : 1 + decPos + digits;
var trimmedResult = numS.substr(0, substrLength);
var finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;
// adds leading zeros to the right
if (decPos != -1){
var s = trimmedResult+"";
decPos = s.indexOf('.');
var decLength = s.length - decPos;
while (decLength <= digits){
s = s + "0";
decPos = s.indexOf('.');
decLength = s.length - decPos;
substrLength = decPos == -1 ? s.length : 1 + decPos + digits;
};
finalResult = s;
}
return finalResult;
};
https://jsfiddle.net/huttn155/7/
function toFixed(number, digits) {
var reg_ex = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)")
var array = number.toString().match(reg_ex);
return array ? parseFloat(array[1]) : number.valueOf()
}
var test = 10.123456789
var __fixed = toFixed(test, 6)
console.log(__fixed)
// => 10.123456
The answer by #kirilloid seems to be the correct answer, however, the main code needs to be updated. His solution doesn't take care of negative numbers (which someone did mention in the comment section but has not been updated in the main code).
Updating that to a complete final tested solution:
Number.prototype.toFixedDown = function(digits) {
var re = new RegExp("([-]*\\d+\\.\\d{" + digits + "})(\\d)"),
m = this.toString().match(re);
return m ? parseFloat(m[1]) : this.valueOf();
};
Sample Usage:
var x = 3.1415629;
Logger.log(x.toFixedDown(2)); //or use whatever you use to log
Fiddle: JS Number Round down
PS: Not enough repo to comment on that solution.
Here my take on the subject:
convert.truncate = function(value, decimals) {
decimals = (decimals === undefined ? 0 : decimals);
return parseFloat((value-(0.5/Math.pow(10, decimals))).toFixed(decimals),10);
};
It's just a slightly more elaborate version of
(f - 0.005).toFixed(2)
Here is simple but working function to truncate number upto 2 decimal places.
function truncateNumber(num) {
var num1 = "";
var num2 = "";
var num1 = num.split('.')[0];
num2 = num.split('.')[1];
var decimalNum = num2.substring(0, 2);
var strNum = num1 +"."+ decimalNum;
var finalNum = parseFloat(strNum);
return finalNum;
}
The resulting type remains a number...
/* Return the truncation of n wrt base */
var trunc = function(n, base) {
n = (n / base) | 0;
return base * n;
};
var t = trunc(5.467, 0.01);
Lodash has a few Math utility methods that can round, floor, and ceil a number to a given decimal precision. This leaves off trailing zeroes.
They take an interesting approach, using the exponent of a number. Apparently this avoids rounding issues.
(Note: func is Math.round or ceil or floor in the code below)
// Shift with exponential notation to avoid floating-point issues.
var pair = (toString(number) + 'e').split('e'),
value = func(pair[0] + 'e' + (+pair[1] + precision));
pair = (toString(value) + 'e').split('e');
return +(pair[0] + 'e' + (+pair[1] - precision));
Link to the source code
const TO_FIXED_MAX = 100;
function truncate(number, decimalsPrecison) {
// make it a string with precision 1e-100
number = number.toFixed(TO_FIXED_MAX);
// chop off uneccessary digits
const dotIndex = number.indexOf('.');
number = number.substring(0, dotIndex + decimalsPrecison + 1);
// back to a number data type (app specific)
return Number.parseFloat(number);
}
// example
truncate(0.00000001999, 8);
0.00000001
works with:
negative numbers
very small numbers (Number.EPSILON precision)
The one that is mark as the solution is the better solution I been found until today, but has a serious problem with 0 (for example, 0.toFixedDown(2) gives -0.01). So I suggest to use this:
Number.prototype.toFixedDown = function(digits) {
if(this == 0) {
return 0;
}
var n = this - Math.pow(10, -digits)/2;
n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56"
return n.toFixed(digits);
}
Here is what I use:
var t = 1;
for (var i = 0; i < decimalPrecision; i++)
t = t * 10;
var f = parseFloat(value);
return (Math.floor(f * t)) / t;
You can work with strings.
It Checks if '.' exists, and then removes part of string.
truncate (7.88, 1) --> 7.8
truncate (7.889, 2) --> 7.89
truncate (-7.88, 1 ) --> -7.88
function truncate(number, decimals) {
const tmp = number + '';
if (tmp.indexOf('.') > -1) {
return +tmp.substr(0 , tmp.indexOf('.') + decimals+1 );
} else {
return +number
}
}
function trunc(num, dec) {
const pow = 10 ** dec
return Math.trunc(num * pow) / pow
}
// ex.
trunc(4.9634, 1) // 4.9
trunc(4.9634, 2) // 4.96
trunc(-4.9634, 1) // -4.9
You can use toFixed(2) to convert your float to a string with 2 decimal points. Then you can wrap that in floatParse() to convert that string back to a float to make it usable for calculations or db storage.
const truncatedNumber = floatParse(num.toFixed(2))
I am not sure of the potential drawbacks of this answer like increased processing time but I tested edge cases from other comments like .29 which returns .29 (not .28 like other solutions). It also handles negative numbers.
just to point out a simple solution that worked for me
convert it to string and then regex it...
var number = 123.45678;
var number_s = '' + number;
var number_truncated_s = number_s.match(/\d*\.\d{4}/)[0]
var number_truncated = parseFloat(number_truncated_s)
It can be abbreviated to
var number_truncated = parseFloat(('' + 123.4568908).match(/\d*\.\d{4}/)[0])
Here is an ES6 code which does what you want
const truncateTo = (unRouned, nrOfDecimals = 2) => {
const parts = String(unRouned).split(".");
if (parts.length !== 2) {
// without any decimal part
return unRouned;
}
const newDecimals = parts[1].slice(0, nrOfDecimals),
newString = `${parts[0]}.${newDecimals}`;
return Number(newString);
};
// your examples
console.log(truncateTo(5.467)); // ---> 5.46
console.log(truncateTo(985.943)); // ---> 985.94
// other examples
console.log(truncateTo(5)); // ---> 5
console.log(truncateTo(-5)); // ---> -5
console.log(truncateTo(-985.943)); // ---> -985.94
Suppose you want to truncate number x till n digits.
Math.trunc(x * pow(10,n))/pow(10,n);
Number.prototype.truncate = function(places) {
var shift = Math.pow(10, places);
return Math.trunc(this * shift) / shift;
};

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

Categories

Resources