2

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?

David Prieto
  • 2,239
  • 4
  • 32
  • 51

9 Answers9

6

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
Community
  • 1
  • 1
Tolgahan Albayrak
  • 3,118
  • 1
  • 25
  • 28
3

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));
manonthemat
  • 6,101
  • 1
  • 24
  • 49
2

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
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

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.

Jonathan Kuhn
  • 15,279
  • 3
  • 32
  • 43
0

Try using toFixed:

number.toFixed(2)
Andrés Andrade
  • 2,213
  • 2
  • 18
  • 23
0

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

Craig Mason
  • 168
  • 6
0

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); }
deblocker
  • 7,629
  • 2
  • 24
  • 59
  • You are probably right, but I can't (or shouldn't) add additional libraries to this particular project. Looks like [manonthemat answer](http://stackoverflow.com/a/41173276/4275425) is the only one that works so far. – David Prieto Jan 13 '17 at 15:17
  • @DavidPrieto: THX for your feedback, as i'm also truly interested in this topic, could you please kindly explain me where my round2() function fails against your accepted trunc() function? It's just onlly because you don't need the Math library or do you have found some other issues? – deblocker Jan 13 '17 at 19:50
  • I'm seeing your edit just now. It looks like both functions work basically the same way, and I just tested that they both fail in round2(2.9999999999999999999999) = 3 – David Prieto Jan 16 '17 at 12:05
0

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


Eman4real
  • 538
  • 5
  • 12
0

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