0

So I made this simple website with html and javascript where the user enters their loose change and it converts it all into a final dollar amount. For some really weird reason, tons of decimal places are added when the nickels and dimes are certain amounts, for example when nickels is 8. Also, even when those decimal places are not like that, the total amount has long decimal places as well. Since none of the calculations should ever go beyond 2 decimal places, it has me kinda stumped. For my solution as you will see in the code, I simply round the number and because this page is for a course in programming and not in math, its not critical that I get it right for the assignment but I am curious as to why this is happening so that if I do ever create something serious in the future, I can avoid this type of issue.

You can view this code in action here, http://192.236.14.50/part4/

Click on Change Converter and enter values and hit convert. If you have the javascript console open, you'll see what I'm talking about. Below is the javascript code.

function registerList3() {
    img = document.getElementById("moneyButton");
    img.addEventListener("click",   function() { calculateMoney(); }, false);

}

// Function calculateMoney tallies up all the change inputs and calculates the total

function calculateMoney() {

    // Create the various var's for each input and assign to their values.
    var pennies = document.getElementById("pennies").value;
    var nickels = document.getElementById("nickels").value;
    var dimes = document.getElementById("dimes").value;
    var quarters = document.getElementById("quarters").value;
    var loonies = document.getElementById("loonies").value;
    var toonies = document.getElementById("toonies").value;
    console.log("Pennies " + pennies);
    console.log("Nickels " + nickels);
    console.log("Dimes " + dimes);
    console.log("Quarters " + quarters);
    console.log("Loonies " + loonies);
    console.log("Toonies " + toonies);

    // Multiply pennies amount by 0.01.
    var penniesAmount = parseFloat(pennies * 0.01);
    // Multiple nickels amount by 0.05.
    var nickelsAmount = parseFloat(nickels * 0.05);
    // Multiple dimes amount by 0.1.
    var dimesAmount = parseFloat(dimes * 0.1);
    // Multiple quarters amount by 0.25.
    var quartersAmount = parseFloat(quarters * 0.25);
    // Loonies amount equals itself, no multiplication needed.
    var looniesAmount = parseFloat(loonies);
    // Multiple toonies amount by 2.
    var tooniesAmount = parseFloat(toonies * 2);

    console.log("-----AMOUNTS-----");
    console.log("Pennies " + penniesAmount);
    console.log("Nickels " + nickelsAmount);
    console.log("Dimes " + dimesAmount);
    console.log("Quarters " + quartersAmount);
    console.log("Loonies " + looniesAmount);
    console.log("Toonies " + tooniesAmount);

    // Create totalAmount var, equal to all amounts added together.
    var totalAmount = penniesAmount + nickelsAmount + 
        dimesAmount + quartersAmount +  looniesAmount + tooniesAmount;
    console.log("Total Amount " + totalAmount);

    // If the total amount is not a number (NaN)...
    if (isNaN(totalAmount)) {
        // Change total label to 0.
        document.getElementById("totalMoney").innerHTML = 0;
        // Alert user to input only numbers.
        alert("Please enter numbers only");
    }
    // Else if total amount is a number...
    else {
        // Create rounded amount and round total amount to 2 decimal places.
        // Shouldn't be neccessary, but it is. See notes above.
        var roundedAmount = Math.round(totalAmount * 100) / 100;
        // Change total money label to rounded amount.
        document.getElementById("totalMoney").innerHTML = roundedAmount;
    }

}

So again, this question isnt about how to just round it, as I have already done that but about why its doing this in the first place. I have never experienced this in any other language.

Passerby
  • 9,715
  • 2
  • 33
  • 50
Richard Chase
  • 407
  • 5
  • 21
  • 2
    Not a solution, merely a comment: when dealing with money, you really should avoid using floating-point numbers. It's much better to deal with integer numbers of dollars and cents. On a side note, entering 0 for everything except nickels (which I set to 8) gives the result of "$0.4" - I don't get the problem you mention. Also, people generally expect to see the whole number of a price, unless the cents are 0, in which case omitting them is fine. I.e $1, $1.10, but not $1.1 - A clear exception is when using a suffix. $1.25k, $1.1m – enhzflep Feb 21 '14 at 04:28
  • 1
    @enhzflep Use parseFloat(0.4)+parseFloat(0.8); and you will see what he is talking about. – Joseph Feb 21 '14 at 04:41
  • Omitting the 0 in the $0.4 instead of $0.40 was a total oversight on my part, I hope I dont lose marks on that although I probably will. So as far as using pure INT's...how would you implement that? Would you simply use single ints for pennies, multiple the int by 10 for dimes, loonies would be 100 etc... and then divide by 100? I just read that article about the floating point math being broke and it makes sense,quite a lot of reading there, so then I guess the solution at least in this particular example would be to use INTs. In any other case, one would need to examine the tradeoffs. Thanks – Richard Chase Feb 22 '14 at 05:18
  • @RichardChase - yep, I'd store the # of cents as an integer. If you mod with 100, you get the number of cents. If you subtract the number of cents from the total figure, then divide by 100, you get the number of dollars. E.g `totalCents = 346; cents = totalCents % 100; dollars = (totalCents - cents) / 100;` - This will give you a value for cents of 46 and a value for dollars of 3. (Note: If you use @username in your comment, it will ensure username will receive a notification of your reply. I just happened to check the question again to see if anything had happened and then saw your response) – enhzflep Feb 25 '14 at 00:00

0 Answers0