2

I am implementing an invoice system, where everything is dynamically added on the dom through javascript and I am making some calculations on the browser itself with javascript. for eg I am calculating each invoice line with quantity and price of unit and generating a total sum

price can be a floating point number

but I am not sure if this should be trusted or not, if someone has the same toughts about javascript please comment :)

I don't know but javascript doesn't seem to me to be trusted like other programming languages like PHP or so, this is my opinion, but if you can convince me please do

Thanks

webmaster
  • 1,960
  • 24
  • 29
  • 5
    You should not use floating point math for monetary calculations in **any** programming language. – Pointy Feb 01 '15 at 15:52
  • @Pointy You have a point, but in JavaScript we don't have types like decimal in C# to make monetary calculations. How we could achieve that you are talking about? Thank you very much in advance. – Christos Feb 01 '15 at 15:54
  • 1
    @Christos Use ints and calculate in cents, then divide by 100. – MisterBla Feb 01 '15 at 15:55
  • 1
    [decimal.js](https://github.com/MikeMcl/decimal.js/), if one wants a prepared solution. – raina77ow Feb 01 '15 at 15:55
  • @RichardA: But don't forget about [the drawbacks of integers](http://floating-point-gui.de/formats/integer/). – Bergi Feb 01 '15 at 16:01
  • 1
    @Bergi That's true. But it's still better than Floating Point numbers. – MisterBla Feb 01 '15 at 16:02
  • @RichardA My payment gateway also use integers, I have to multiply the price by 100 first and then send the payment to their system. Maybe they know something I don't know :) I think i'll go like that.. – webmaster Feb 01 '15 at 16:44

4 Answers4

3

Javascript uses the same data type that almost all languages use for floating point calculations. The double precision floating point data type is very common, because processors have built in support for it.

Floating point numbers have a limited precision, and most numbers with a fractional part can't be represented exactly. However, for what you are going to use it for, the precision is more than enough to show a correct result.

You should just be aware of the limited precision. When displaying the result, you should make sure that it's formatted (and rounded) to the precision that you want to show. Otherwise the limited precision might show up as for example a price of 14.9500000000000001 instead 14.95.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • "*most* numbers" sounds funny. If you take the infinite set of [numbers with a fractional part](https://en.wikipedia.org/wiki/Rational_number), those few 2^64 representable values are nothing… :-) – Bergi Feb 01 '15 at 17:13
2

According to JavaScript's specifications, all numbers are 64bit precision (as in 64bit floating point precision).

From this post, you have 3 solutions:

  1. use some implementation of Decimal for JavaScript, as BigDecimal.js
  2. just choose a fixed number of digits to keep, like this (Math.floor(y/x) * x).toFixed(2)
  3. switch to pure integers, treating prices as number of cents. This could lead you to big changes across the whole project
Community
  • 1
  • 1
le0m
  • 398
  • 1
  • 4
  • 14
2

Financial calculations usually require specific fixed rules about (for example) when and how to round (in which direction), etc.
That means you'll often maintain an internal sub-total precision until you move to a next section of your calculation (like adding the tax, as per rules set).

IEEE-754 Floating point (as used in javascript) will give you a maximum accuracy of 2^53 (if you think about it like an integer).
Now your 'job' is to pretend javascript doesn't support floating point and substitute it yourself using the simplest possible way: decrease your maximum integer range to obtain the required floating point precision and see if that resulting range is suitable to your needs. If not, then you might need an external high precision math library (although most basic operations are pretty easy to implement).

First determine your desired internal precision (incl overflow digit for your expected rounding behavior): for example 3 digits:
FLOOR((2^53)/(10^3))=FLOOR(9.007.199.254.740.992/1000)=9.007.199.254.740,000
If this range is sufficient, then you need no other library, just multiply your input 10^float_digits and maintain that internal precision per calculation-section, while rounding each step according to the rules required for your calculation (you'd still need to do that when using a high-precision external math library).

For (visual) output, again, apply proper rounding and just divide your remaining value by 10^(floatDigits-roundingDigit(s)) and pass it through Number.prototype.toFixed() (which then just pads zero's when required).



As to your other question regarding trustworthiness of javascript vs other programming languages: one can even boot/run and use LINUX on javascript inside the browser: http://bellard.org/jslinux/
Let that sink in for a moment...
Now what if I told you this even works in IE6... Pretty humbling. Even servers can run on javascript (node.js)..

Hope this helps (it didn't fit in a comment).

GitaarLAB
  • 14,536
  • 11
  • 60
  • 80
0

Other answers have addressed issues that JavaScript has with using floating point numbers to represent money.

There's a separate issue with using JavaScript for calculations involving financial transactions that comes to mind. Because the code is executed in a browser on the client machine, You can only trust the result to the extent that you can trust the client.

Therefore you should really only rely on JavaScript to calculate something that you could take for granted if the client told you. For instance, if you were writing an e-commerce site, you could trust code that told you what the client wanted to buy, and what the clients shipping address was, but you would need to calculate the price of the goods yourself to prevent the client from telling you a lower price.

It's entirely possible that the invoicing system you're working on will only be used internally to your organisation. If this is the case, you can disregard this entire answer. But, if your applications is going to be used by customers to access and manipulate their invoices and orders, then this is something you'd have to consider.

Joe
  • 1,479
  • 13
  • 22