51

I have javascript function that automatically adds input fields together, but adding numbers like 1.35 + 1.35 + 1.35 gives me an output of 4.050000000000001, just as an example. How can I round the total to the second decimal instead of that long string?

The input fields will have more than just the 1.35 example so I need the total to never have more than 2 points after the decimal. Here is the full working code:

<html>
<head>
<script type="text/javascript">
function Calc(className){
var elements = document.getElementsByClassName(className);
var total = 0;

for(var i = 0; i < elements.length; ++i){
total += parseFloat(elements[i].value);
}

document.form0.total.value = total;
}

function addone(field) {
  field.value = Number(field.value) + 1;
  Calc('add');
}
</script>
</head>
<body>
<form name="form0" id="form0">
1: <input type="text" name="box1" id="box1" class="add" value="0" onKeyUp="Calc('add')" onChange="updatesum()" onClick="this.focus();this.select();" />
<input type="button" value=" + " onclick="addone(box1);">
<br />

2: <input type="text" name="box2" id="box2" class="add" value="0" onKeyUp="Calc('add')" onClick="this.focus();this.select();" />
<input type="button" value=" + " onclick="addone(box2);">
<br />

<br />
Total: <input readonly style="border:0px; font-size:14; color:red;" id="total" name="total">
<br />
</form>
</body></html>

Some things I have tried, which should work but I am clearly implementing them incorrectly:

for(var i = 0; i < elements.length; ++i){
total += parseFloat(elements[i].value.toString().match(/^\d+(?:\.\d{0,2})?/));

var str = total.toFixed(2);

or

for(var i = 0; i < elements.length; ++i){
total += parseFloat(elements[i].value * 100) / 100).toFixed(2)

Have also had no luck with Math.floor

JB.
  • 893
  • 3
  • 16
  • 29
  • You don't really need to post all the code, as it's not really relevant to the question here. Only post the relevant bits. – moinudin Jan 09 '11 at 17:04
  • FYI: Your second (related to toFixed) snippet has a syntax error. –  Jan 09 '11 at 17:37
  • For future reference it was resolved thanks to @marcog by using: `document.form0.total.value = total.toFixed(2);` – JB. Jan 09 '11 at 19:21
  • Isn't it worthwhile to understand why the sum equals such a long number of decimal points? – Kevin Meredith Dec 03 '12 at 18:08
  • For future reference: because how Javascript manages float values, the number 1.35 *Can't be exactly saved in a variable, or even computed*. Try this in a Javascript console `(1.35).toPrecision(52)`, it'll show you that the *real* value or `1.35` in Javascript is `1.350000000000000088817841970012523233890533447265625` (all decimal beyond that are all 0). – Roimer Oct 09 '13 at 13:52

5 Answers5

78

Use toFixed() to round num to 2 decimal digits using the traditional rounding method. It will round 4.050000000000001 to 4.05.

num.toFixed(2);

You might prefer using toPrecision(), which will strip any resulting trailing zeros.

Example:

1.35+1.35+1.35 => 4.050000000000001
(1.35+1.35+1.35).toFixed(2)     => 4.05
(1.35+1.35+1.35).toPrecision(3) => 4.05

// or...
(1.35+1.35+1.35).toFixed(4)     => 4.0500
(1.35+1.35+1.35).toPrecision(4) => 4.05

Reference: JavaScript Number Format - Decimal Precision

biesior
  • 55,576
  • 10
  • 125
  • 182
moinudin
  • 134,091
  • 45
  • 190
  • 216
  • The reference is helpful, but I cant figure out what I am doing wrong, it must be my placement of 'toFixed'. My comments above give more detail to the end goal – JB. Jan 09 '11 at 17:34
  • @Josh Your second snippet is bad, you don't want to round after every addition. Your first one looks right though - what problem is that giving you? Are you sure you're using `str` afterwards? – moinudin Jan 09 '11 at 17:42
  • 1
    When you get it fixed, mark this one as the answer. He's gone far more in-depth to accommodate you. –  Jan 09 '11 at 17:48
  • Thanks You enlightened me with a new methods 'toFixed' and 'toPrecision'.+1ed – Ravi Jul 31 '12 at 10:19
  • 2
    why do I get (1.35+1.35+1.35).toPrecision(4) => '4.050' – lajarre Oct 30 '15 at 19:12
4
var num = 4.050000000000001;

num = num.toFixed(2);

toFixed will round up depending on how many digits after the decimal you're looking for.

  • Im looking to have the total (what ever the total ends up being) never have more than 2 numbers after the decimal. The total could be 6.300000000000001. Ive tried using different variations of 'toFixed' but I cant figure out where to put it to have the total never have more than 2 after the decimal – JB. Jan 09 '11 at 17:27
  • 2
    @Josh Call `toFixed` on the value before displaying it, e.g. `document.form0.total.value = total.toFixed(2)`; – moinudin Jan 09 '11 at 17:36
  • @marcog that did the trick. I have a second field that divides the total by 25 that I am also looking to limit the decimal but the same code is not working: `document.form0.divided.value = total / 25.toFixed(2);` – JB. Jan 09 '11 at 17:48
  • @Josh `(total / 25).toFixed(2)` - you always want to perform the rounding at the very last step. – moinudin Jan 09 '11 at 17:51
2

You can use Math.round(total*100000000000)/100000000000; in the code. It will work for most of the cases

1

This works:

$(document).ready(
    function() {
            $('#field1').blur(function(){ $('#field2').val(parseFloat($(this).val() * 2.2).toFixed(1)); });
            $('#field2').blur(function(){ $('#field1').val(parseFloat($(this).val() / 2.2).toFixed(1)); });
    }
);

This fails:

$(document).ready(
    function() {
            $('#field1').blur(function(){ $('#field2').val(parseFloat($(this).val() * 2.2)).toFixed(1); });
            $('#field2').blur(function(){ $('#field1').val(parseFloat($(this).val() / 2.2)).toFixed(1); });
    }
);

So be careful the way you place your parenthesis ()... In first case, the rounding will work, but won't work in the second one...

  • You should make it clear when jQuery is a prerequisite, as it might be confusing and frustrating for a beginner to enter this code without a jQuery library and find that it doesn't work. Not everyone uses jQuery. – k-den Feb 26 '13 at 15:42
1

Instead of rounding, you may want to use the port of Java's BigDecimal to get actually precise decimal math.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720