-1
var quantity = $(this).find('td:eq(2) input').val()*1;
var unitprice = $(this).find('td:eq(3) input').val()*1;
var totaltax = 0;
$(this).find('td:eq(4) input[name^=taxamount]').each(function(){
    totaltax = (totaltax*1)+($(this).val()*1);
});
var subtotal = (unitprice+totaltax);
alert(subtotal+' is unit subtotal, to mulitply by '+quantity);
var total = subtotal*quantity;
$(this).find('td:last').html('$'+total);

In this case, based on my DOM, the results are all integers (especially because I'm making sure I apply the *1 modifier to values to ensure they are numbers, not strings).

In this case, these are teh values returned within the first 7 lines of the above code (and verified through alert command) quantity: 10 unitprice: 29 totaltax: 3.48 subtotal = 32.48

When I multiply subtotal*quantity for the total variable, total returns: total: 324.79999999999995

So at the end, I get the td:last filled with $324.79999999999995 rather than $324.80 which would be more correct.

Bizarre, I know. I tried all sorts of alerts at different points to ensure there were no errors etc.

Jacek Kaniuk
  • 5,229
  • 26
  • 28
jeffkee
  • 5,106
  • 12
  • 44
  • 76
  • 5
    no, it isn't bizarre. simple floating-point arithemtic. – Karoly Horvath Aug 09 '11 at 22:17
  • 1
    Welcome to the world of floating point arithmetic. – zzzzBov Aug 09 '11 at 22:17
  • floating point arithmetic: http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html – BrokenGlass Aug 09 '11 at 22:17
  • 1
    See [here](http://stackoverflow.com/questions/2480699/understanding-floating-point-variables) – bfavaretto Aug 09 '11 at 22:17
  • Should not rely on floating point numbers for money calculations. @Sparky - I think the title is wrong - it should be `32.48 * 10`. – Anurag Aug 09 '11 at 22:22
  • What's with all the down votes. Not everyone is born with an innate knowledge of floating point computation. And jeffkee has demonsrated he's tried to find out what is causing the problem before asking the question. – Dunes Aug 09 '11 at 22:26
  • Thank you Dunes, if I were a programming maven I wouldn't be on this site. Besides, this could add to the pool of knowledge. Who knows, Google may pick this up more. When I did my search, it was related more to the theorem, and some actionscript articles came up, which didn't help. Also I couldn't be sure if I just round it up/down (which I obviously know how to do), if it would still be the "improper" way, so I asked. – jeffkee Aug 09 '11 at 22:45

7 Answers7

7

This has been asked one bizillion times.

Please read: What Every Computer Scientist Should Know About Floating-Point Arithmetic

Vinicius Kamakura
  • 7,665
  • 1
  • 29
  • 43
4

You're coming up against a familiar issue with floating point values: certain values can't be precisely represented in a finite binary floating point number.

See here:

How to deal with floating point number precision in JavaScript?

Community
  • 1
  • 1
Trevor
  • 10,903
  • 5
  • 61
  • 84
  • Thank you for an actually "practical" solution. Some of these guys on this site like to sound smart with ambiguous & condescending answers that don't really help me in completing my task & learning further... – jeffkee Aug 09 '11 at 22:46
3

This is the way floating point numbers work. There's nothing bizarre going on here.

I'd recommend that you round the value appropriately for display.

duffymo
  • 305,152
  • 44
  • 369
  • 561
1

That's the joy of floating point arithmetic -- some base 10 decimals cannot be represented in binary.

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

Dunes
  • 37,291
  • 7
  • 81
  • 97
1

Computers can't handle decimals very well in binary since in real mathematics there are literally an infinite number of values between 0.01 and 0.02 for example. So they need to store approximations, and when you do arithmetic on those approximations the results can get a little away from the true result.

You can fix it with (Math.round(total*100)/100).toFixed(2);

Paul
  • 139,544
  • 27
  • 275
  • 264
1

As others have mentioned, this is the way its meant to work. A suggested workaround can be found below:

var v = "324.32999999999995";

function roundFloat(n, d) {             
    var a= Math.pow(10, d);             
    var b= Math.round(n * a) / a;
    return b;         
}

$("body").append(roundFloat(v,3));

Where v would be replaced with the desired value.

You can view the working example at: http://jsfiddle.net/QZXhc/

Robert
  • 8,717
  • 2
  • 27
  • 34
  • Awesome, this is an amazing function to add to my framework! Thanks a million. I wonder if jQuery already has something like this built in? – jeffkee Aug 09 '11 at 22:47
0

You could try rounding to 2 decimal digits as workaround

Im0rtality
  • 3,463
  • 3
  • 31
  • 41