2

I would like it so that each time a (toppings) checkbox is checked, it updates the price by adding an additional 99 pence. It all works fine, except when the user selects the 3 checkboxes (which is 0.99 * 3) and it displays 2.9699999999999998 instead of 2.97

Any ideas on what's wrong?

HTML:

<label><b>Toppings (99p Each): &nbsp;</b></label><br>
<input type="checkbox" name="onions">Onions</input><br>
<input type="checkbox" name="mushrooms">Mushrooms</input><br>
<input type="checkbox" name="peppers">Peppers</input><br>
<input type="checkbox" name="olives">Olives</input><br>
<input type="checkbox" name="garlic">Garlic</input><br>
<input type="checkbox" name="xtra-cheese">Xtra Cheese</input><br>
<input type="checkbox" name="peperoni">Peperoni</input><br>

JavaScript:

var pizzaCost = 0.00;
var toppingCost = 0.00;

$('input[type=checkbox]').change(function(){
    var checked = $(":checkbox:checked").length;
    var checkedInt = parseFloat(checked, 10);
    var temp = (0.99 * checkedInt);
    toppingCost = parseFloat(temp);
    var total = pizzaCost + toppingCost;
    $("#totalPrice").text(total);
});
SamG
  • 303
  • 4
  • 13
  • 1
    [`parseFloat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat) is used to convert a *string* to a float value. Unlike `parseInt`, it *does not* have a 2nd parameter. JavaScript actually does not have different types for ints and floats, they are both the same. So, `parseFloat(checked)` does *nothing*. This will actually convert `checked` to a *string* then to a float. – gen_Eric Dec 02 '15 at 17:52
  • See https://stackoverflow.com/questions/588004/is-floating-point-math-broken – rogerdpack Aug 30 '19 at 06:21

5 Answers5

4

parseFloat is used to convert a string to a float value. Unlike parseInt, parseFloat does not have a 2nd parameter.

JavaScript actually does not have different types for ints and floats, they are both the same (and stored internally as floats). The only difference between parseFloat and parseInt is whether the returned number should have a decimal component or not.

What you want to use here is toFixed(), parseFloat is not needed here at all. There are no strings that you need to parse.

$('input[type=checkbox]').change(function(){
    var checked = $(":checkbox:checked").length;
    toppingCost = 0.99 * checked;

    var total = pizzaCost + toppingCost;
    $("#totalPrice").text(total.toFixed(2));
});
gen_Eric
  • 223,194
  • 41
  • 299
  • 337
2

Floating point numbers are rarely exact. They work by representing a number with the least possible error - a little bit like compression. This is in contrast to Decimal datatypes in some languages which literally do store every number like an integer, even past the decimal.

The longer the float, the more precise it is. Most floats are the 32-bit variant of the IEEE 754 standard which has a 23-bit mantissa (the fractional part or precision), and an 8-bit exponent which essentially moves the "floating" decimal point along the mantissa.

What this means for you is that 2.97 cannot be expressed with floats without a small margin of error. In order to get 2.97, you need to round the result to 2d.p. In JavaScript you can do this with

toppingCost.toFixed(2) 
Chris Watts
  • 6,197
  • 7
  • 49
  • 98
1

here is a idea multiply the number with 100 then divide the result by 100: 0.99*100*3/100 https://jsfiddle.net/qp21bpbs/1/

madalinivascu
  • 32,064
  • 4
  • 39
  • 55
  • 1
    This is a good idea. You basically treat everything in *cents* instead of dollars. – gen_Eric Dec 02 '15 at 18:44
  • P.S. You have *way* too many `parseFloat`s in your jsFiddle. No idea why. You can (and should) lose them all. – gen_Eric Dec 02 '15 at 18:44
  • @RocketHazmat just copied the question and added the 100's,i convert the dollars to cents by multiplying by 100 and convert back to dolars by dividing the answer to 100 basic math – madalinivascu Dec 02 '15 at 19:05
0

try: parseFloat(x).toFixed(2) let me know if you need something else.

zer00ne
  • 41,936
  • 6
  • 41
  • 68
0

parseFloat is to parse strings to float values, to get some formated float you should use toFixed, like this:

var pizzaCost = 0.00;
var toppingCost = 0.00;

$('input[type=checkbox]').change(function(){
    var checked = $(":checkbox:checked").length;
    var checkedInt = parseFloat(checked, 10);
    var temp = (0.99 * checkedInt);
    toppingCost = +temp.toFixed(2); // Assuming 2 decimals
    var total = pizzaCost + toppingCost;
    $("#totalPrice").text(total);
});
  • You can lose the `checkedInt` variable. `parseFloat(checked, 10)` is completely uselsess. – gen_Eric Dec 02 '15 at 18:08
  • 1
    Yes, you can clean that code, i just changed it to work, the "JQuery.length" should return an Int already :) So this should work just fine: total = pizzaCost + +( checked * toppingCost ).toFixed( 2 ) – Diogo Neves - Mangaru Dec 03 '15 at 16:15