David Prieto
David Prieto

Reputation: 2299

How to truncate decimals in JavaScript without Math library?

I need numbers to have only 2 decimals (as in money), and I was using this:

Number(parseFloat(Math.trunc(amount_to_truncate * 100) / 100));

But I can no longer support the Math library.

How can I achieve this without the Math library AND withou rounding the decimals?

Upvotes: 2

Views: 5082

Answers (9)

You can try this

function trunc(value){
    return (!!value && typeof value == "number")? value - value%1 : 0;
}
console.log(trunc(1.4));
console.log(trunc(111.9));
console.log(trunc(0.4));
console.log(trunc("1.4"));

Upvotes: 0

Eman4real
Eman4real

Reputation: 597

This was a lot easier than I thought:

const trunc = (number, precision) => {
  let index = number.toString().indexOf(".");
  let subStr;

  // in case of no decimal
  if (index === -1) {
    subStr = number.toString();
  }
  // in case of 0 precision
  else if (precision === 0) {
    subStr = number.toString().substring(0, index);
  }
  // all else
  else {
    subStr = number.toString().substring(0, index + 1 + precision);
  }
  return parseFloat(subStr);
};

let x = trunc(99.12, 1);

console.log("x", x);


Upvotes: 0

Craig Mason
Craig Mason

Reputation: 168

You could parseInt to truncate, then divide by 100 and parseFloat.

var num = 123.4567;
num=parseInt(num*100);
num=parseFloat(num/100);
alert(num);

See fiddle

Edit: in order to deal with javascript math craziness, you can use .toFixed and an additional digit of multiplication/division:

var num = 123.4567;
num = (num*1000).toFixed();
num = parseInt(num/10);
num = parseFloat(num/100);
alert(num);

Updated fiddle

Upvotes: 0

Tolgahan Albayrak
Tolgahan Albayrak

Reputation: 3206

You can use toFixed

Number(amount_to_truncate.toFixed(2))

If you are sure that your input always will be lower or equal than 21474836.47 ((2^31 - 1) / 100) (32bit) then:

if you need as string (to make sure result will have 2 decimals)

((amount_to_truncate * 100|0)/100).toFixed(2)

Otherwise

((amount_to_truncate * 100|0)/100)

Else: See Nina Schols's answer

console.log((((15.555 * 100)|0)/100)) // will not round: 15.55
console.log((((15 * 100)|0)/100).toFixed(2)) // will not round: 15.55

Upvotes: 6

deblocker
deblocker

Reputation: 7697

Truncate does also a rounding, so your statement: "I need numbers to have only 2 decimals ... without rounding the decimals" seems to me a little bit convoluted and would lead to a long discussion.

Beside this, when dealing with money, the problem isn't Math but how you are using it. I suggest you read the Floating-point cheat sheet for JavaScript - otherwise you will fail even with a simple calculation like 1.40 - 1.00.

The solution to your question is to use a well-tested library for arbitrary-precision decimals like bignumber.js or decimals.js (just as an example).

EDIT:

If you absolutely need a snippet, this is how i did it some time ago:

function round2(d) { return Number(((d+'e'+2)|0)+'e-'+2); }

Upvotes: 0

manonthemat
manonthemat

Reputation: 6251

Make it simple

const trunc = (n, decimalPlaces) => {
  const decimals = decimalPlaces ? decimalPlaces : 2;
  const asString = n.toString();
  const pos = asString.indexOf('.') != -1 ? asString.indexOf('.') + decimals + 1 : asString.length;
  return parseFloat(n.toString().substring(0, pos));
};

console.log(trunc(3.14159265359));
console.log(trunc(11.1111111));
console.log(trunc(3));
console.log(trunc(11));
console.log(trunc(3.1));
console.log(trunc(11.1));
console.log(trunc(3.14));
console.log(trunc(11.11));
console.log(trunc(3.141));
console.log(trunc(11.111));

Upvotes: 3

Nina Scholz
Nina Scholz

Reputation: 386604

You could use parseInt for a non rounded number.

console.log(parseInt(15.555 * 100, 10) / 100); // 15.55 no rounding
console.log((15.555 * 100 | 0) / 100);         // 15.55 no rounding, 32 bit only 
console.log((15.555).toFixed(2));              // 15.56 rounding

Upvotes: 2

Jonathan Kuhn
Jonathan Kuhn

Reputation: 15301

The only thing I see wrong with toFixed is that it rounds the precision which OP specifically states they don't want to do. Truncate is more equivalent to floor for positive numbers and ceil for negative than round or toFixed. On the MDN page for the Math.trunc there is a polyfill replacement function that would do what OP is expecting.

Math.trunc = Math.trunc || function(x) {
  return x - x % 1;
}

If you just used that, then the code wouldn't have to change.

Upvotes: 2

Andrés Andrade
Andrés Andrade

Reputation: 2223

Try using toFixed:

number.toFixed(2)

Upvotes: 0

Related Questions