skip to Main Content

I have a fee, and I’m trying to calculate the installment amount of paying the fee in X installments. What I want is to round (or floor – I’m not sure about that spec yet) X-1 installments, and then calculate the last installment based on the remaining fee.

So I did the following, but the last installment has many integers. It’s a simple subtraction, why does it lose its precision?

Also, would you calculate the whole concept in a different way?

let tuitionFee = 1000;
let numberOfInstallments = 7;

let roundedInstallments = Math.round(tuitionFee / numberOfInstallments * 100) / 100;
let lastInstallment = tuitionFee - (roundedInstallments * (numberOfInstallments - 1));

console.log(tuitionFee / numberOfInstallments);
console.log(roundedInstallments);
console.log(lastInstallment);

2

Answers


  1. Generally, floating point math should be arranged in a way that minimizes error. In this case, it makes sense to have pennies as the unit. This would reduce error by making it so that most calculations are applied to integers. So we modify it to do that and only convert to dollars for display.

    let tuitionFee = 1000 * 100;
    let numberOfInstallments = 7;
    
    let roundedInstallments = Math.round(tuitionFee / numberOfInstallments);
    let lastInstallment = tuitionFee - roundedInstallments * (numberOfInstallments - 1);
    
    console.log(tuitionFee / numberOfInstallments / 100);
    console.log(roundedInstallments / 100);
    console.log(lastInstallment / 100);
    Login or Signup to reply.
  2. You may use these 2 general functions:

    const fixFloat = function(val) { 
        // Handle values with '.' as thousand separator(s) and ',' as decimal separator
        // eg.: val = '12.000,50', '12.000.000,50', '12000,50' or 12000.50
        let n = val.toString();
        if (/./.test(n) && /,/.test(n)) { // Contains both '.' and ',' ?
            n = n.replace(/(.)/g, ''); // remove all '.'
        }
        if (!/,.*,/.test(n) && /,/.test(n)) { // Contains a single ',' ?
            n = n.replace(/(,)/g, '.'); // replace ',' by '.'
        }
    
        return isNaN(n) ? 0 : parseFloat(n);
    
    }
    const round = function (val, places) {
        // ---------------------------------------------------
        // Purpose: Round value to spesific number of desimals
        // val    : Value to round
        // places : number of desimals
        // ---------------------------------------------------
        var value = fixFloat(val).toString();
        var a = value.split('.');
        var d = a.length == 2 ? a[1] : '0';
        value = a[0] ? a[0] : '0';
    
        if (!places) { places = 0; }
        if (places < d.length) { d = places ? Math.round(d.substr(0, places) + '.' + d.substr(places, 1)) : Math.round(d.substr(0, 1) + '.' + d.substr(1, 1)); }
        if (d) { value += '.' + d; }
        if (!places) { value = Math.round(value); }
    
        return parseFloat(value);
    }
    
    let tuitionFee = 1000;
    let numberOfInstallments = 7;
    let roundedInstallments = round(tuitionFee / numberOfInstallments, 2);
    let lastInstallment = round(tuitionFee - (roundedInstallments * (numberOfInstallments-1)), 2);
    
    console.log(roundedInstallments); // 142.86
    console.log(lastInstallment);   // 142.84
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search