1

So, I've been having trouble trying to prevent toFixed from rounding up numbers, what I want to achieve is that, for a certain number, multiply that number to a specific number and then return the last two digits without rounding up.

I have read the following thread: javascript - how to prevent toFixed from rounding off decimal numbers.

As a matter of fact, I have tried the solution of Santiago Hernandez.

This is the fiddle: demo

Examples: 6500 * 0.0002 = 1.3

In this case, the result is 1. and does not take the 3 in consideration.

var multiplier = 0.0002;
var num = 500 * multiplier;

var toFixed = function(val, decimals) {
  var arr = ("" + val).split(".")
  if(arr.length === 1) 
    return val
  var int = arr[0],
      dec = arr[1],
      max = dec.length - 1
  return decimals === 0 ? int :
    [int,".",dec.substr(0, decimals > max ? max : decimals)].join("")
}

I imagine is this part:

max = dec.length - 1

What I have tried: I took out the - 1 and I tried with 10 different types of numbers (987.77, 6600.77, etc) but I wanted to know if there is another type of solution or if at some point the above code will fail for some digits.

Nickso
  • 785
  • 1
  • 10
  • 32
  • 1
    There's a `Number.toFixed()` builtin in javascript. But for rounding, you should use `Math.round()` and it's brethren. So `( 6500 * 0.0002 ).toFixed( 2 );` will produce the `string` "1.30". If you want trailing zeroes, you always have to use a string, since trailing zeroes have no meaning in numbers. So the usual way is to do all calculations with numbers,then using `Math.ceil()` or `Math.floor()` to get the wanted rounding and finally formatting them using toFixed() at the end. – Shilly Dec 18 '18 at 13:25
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed – Jared Smith Dec 18 '18 at 13:31

2 Answers2

0

That's my toFixed alternative, that don't round numbers, just truncates it or adds zeroes according to given precision. For extra long number it uses JS build-in rounding when precision is to long. Function works for all problematic number I've found on stack.

function toFixedFixed(value, precision = 0) {
    let stringValue = isNaN(+value) ? '0' : String(+value);

    if (stringValue.indexOf('e') > -1 || stringValue === 'Infinity' || stringValue === '-Infinity') {
        throw new Error('To large number to be processed');
    }

    let [ beforePoint, afterPoint ] = stringValue.indexOf('.') > -1 ? stringValue.split('.') : [ stringValue, ''];

    // Force automatic rounding for some long real numbers that ends with 99X, by converting it to string, cutting off last digit, then adding extra nines and casting it on number again
    // e.g. 2.0199999999999996: +('2.019999999999999' + '9999') will give 2.02
    if (stringValue.length >= 17 && afterPoint.length > 2 && +afterPoint.substr(afterPoint.length - 3) > 995) {
        stringValue = String(+(stringValue.substr(0, afterPoint.length - 1) + '9'.repeat(stringValue.split('.').shift().length + 4)));
        [ beforePoint, afterPoint ] = String(stringValue).indexOf('.') > -1 ? stringValue.split('.') : [ stringValue, ''];
    }

    if (precision === 0) {
        return beforePoint;
    } else if (afterPoint.length > precision) {
        return `${beforePoint}.${afterPoint.substr(0, precision)}`;
    } else {
        return `${beforePoint}.${afterPoint}${'0'.repeat(precision - afterPoint.length)}`;
    }
}

MagyaDEV
  • 375
  • 3
  • 8
0

An alternative implementation: Add a value, so that math-rounding is changed to rounding-toward-zero:

function toCut ( num, digits )
{
    let x = parseFloat("0.5e-"+digits);
    return ( num < 0 ? num+x : num-x ).toFixed(digits);
}
Wiimm
  • 2,971
  • 1
  • 15
  • 25