Oscar
Oscar

Reputation: 3701

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?

Upvotes: 369

Views: 536124

Answers (30)

Mohsen Robatjazi
Mohsen Robatjazi

Reputation: 194

Reading and inspecting all the answers , I assumed it would be a good idea to share another approach to achieve "Getting Fractional Part of Number in js" :

const fractionCount = (number)=>{
    let count = 0;
    while(number !== Math.floor(number)){
        number*=10;
        count++;        
    }
    return count;    
}

console.log(fractionCount(2.3456790))

Upvotes: 0

Grzegorz Raczek
Grzegorz Raczek

Reputation: 11

Wow, leave it to StackOverflow to overcomplicate things.

Why not just do this:

function splitDecimals(amt: number): [number, number] {
    const integerPart =
      (amt < 0 ? '-' : '') + Math.floor(Math.abs(amt)).toString();
    const amountString = amt.toString();
    const decimalPart =
      amountString.length > integerPart.length
        ? amountString.slice(integerPart.length)
        : '0';
    return [Number.parseInt(integerPart), Number.parseFloat(decimalPart)];
  }

If you ignore the Number.parseX you get two nice strings, otherwise you get two nice numbers, which is the best you can do if you don't know the number of decimals.

123.4567 => [123, 0.4567]
0.111222333444555 => [0, 0.111222333444555]
-123.4567 => [-123, 0.4567]
123.111222333444 => [123, 0.111222333444]
111222333444555.11 => [111222333444555, 0.11]
2230000000 => [2230000000, 0]

Upvotes: -1

Zantafio
Zantafio

Reputation: 567

Here's how I do it, which I think is the most straightforward way to do it:

var x = 3.2;
var int_part = Math.trunc(x); // returns 3
var float_part = Number((x-int_part).toFixed(2)); // return 0.2

Upvotes: 42

masterxilo
masterxilo

Reputation: 2788

Just use modulo 1.

remainder = x % 1;

Upvotes: 11

Nurlan
Nurlan

Reputation: 813

Without relying on any standard JS functions:

var a = 3.2;
var fract = a * 10 % 10 /10; //0.2
var integr = a - fract; //3

Note that it is correct only for numbers with one decimal point.

Upvotes: 13

aggregate1166877
aggregate1166877

Reputation: 3220

Yet another way:

function fract(x) {
  return 1 - (Math.ceil(x) - x);
}

fract(2.3) // <-- 0.2999999999999998

Upvotes: 0

Solution

The simplest way is to use the mod (%) operator:

var decimal = n % 1;

Explanation

The mod operator gives the remainder of the arithmetical division.

Example: 14 % 4 is 2 because 14 / 4 is 3 and its remainder is 2.

Then, since n % 1 is always between 0 and 1 or [0, 1) it corresponds to the decimal part of n.

Upvotes: 6

ali t
ali t

Reputation: 17

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);
}

Upvotes: 0

Rifat Mahmud
Rifat Mahmud

Reputation: 175

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)

Upvotes: 0

edalvb
edalvb

Reputation: 724

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));

Upvotes: 0

Tang Chanrith
Tang Chanrith

Reputation: 1459

You can simply use parseInt() function to help, example:

let decimal = 3.2;
let remainder = decimal - parseInt(decimal);
document.write(remainder);

Upvotes: 4

vanowm
vanowm

Reputation: 10221

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 ]

Upvotes: 0

William Brendel
William Brendel

Reputation: 19

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

Upvotes: 0

Pawel Cioch
Pawel Cioch

Reputation: 3192

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!

Upvotes: 1

nanobar
nanobar

Reputation: 66455

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))

Upvotes: 3

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]];

Upvotes: 7

user1742529
user1742529

Reputation: 264

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:

  1. parseFloat() for guaranteeing input cocrrection
  2. Math.abs() for avoiding problems with negative numbers
  3. n = parseInt(x) for getting decimal part
  4. x - n for substracting decimal part
  5. We have now number with zero decimal part, but JavaScript could give us additional floating part digits, which we do not want
  6. 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.

Upvotes: 0

Sheki
Sheki

Reputation: 1635

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]}`)
       }
   }
}

Upvotes: 9

Hifzur Rahman
Hifzur Rahman

Reputation: 103

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)

Upvotes: 1

Vasilii Suricov
Vasilii Suricov

Reputation: 954

Math functions are faster, but always returns not native expected values. Easiest way that i found is

(3.2+'').replace(/^[-\d]+\./, '')

Upvotes: 2

Gabriel Hautclocq
Gabriel Hautclocq

Reputation: 3320

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.

Upvotes: 8

DavidDunham
DavidDunham

Reputation: 1362

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

Upvotes: 3

Ethan
Ethan

Reputation: 3818

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

Upvotes: 31

Elim Garak
Elim Garak

Reputation: 1827

After looking at several of these, I am now using...

var rtnValue = Number(7.23);
var tempDec = ((rtnValue / 1) - Math.floor(rtnValue)).toFixed(2);

Upvotes: 0

peksipatongeis
peksipatongeis

Reputation: 11

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.

Upvotes: 1

cdmdotnet
cdmdotnet

Reputation: 1753

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.

Upvotes: 6

David S&#225;nchez
David S&#225;nchez

Reputation: 634

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)

Upvotes: 4

jomofrodo
jomofrodo

Reputation: 1149

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".

Upvotes: 43

gion_13
gion_13

Reputation: 41533

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');

Upvotes: 2

sdleihssirhc
sdleihssirhc

Reputation: 42496

You could convert to string, right?

n = (n + "").split(".");

Upvotes: 103

Related Questions