0
let price: number = 0.7; // $
let discountPrice: number = 0.6; // $

let netPrice: number = price - discountPrice;

console.log(netPrice); // 0.09999999999999998 but not 1 cent

Due to IEEE 754 standard, we are losing data precision after computation.

How client side calculations are done in ecommerce applications? to maintain precision

Mike Aguilar
  • 348
  • 2
  • 3
  • 14
overexchange
  • 15,768
  • 30
  • 152
  • 347
  • `How client side calculations are done in ecommerce applications?` Rounding. – user229044 May 09 '18 at 00:49
  • @meagar Do we need to always use`somePrice.toFixed(1)`? that relate to currency – overexchange May 09 '18 at 00:55
  • Only when you display the numbers to a user. – user229044 May 09 '18 at 00:58
  • @meagar But anyways am losing the value precision in the data, due to problems in representation – overexchange May 09 '18 at 00:59
  • When calculating in currency, you should do the math in pennies/cents and then times by 100. Otherwise, you will run into rounding issues like this. – James May 09 '18 at 01:03
  • 3
    @overexchange You're talking about client-side calculations in JavaScript, so my assumption here is that you are displaying something like a shopping cart and your problem is that you need to render dollar values rounded to two decimal places. The accuracy of your calculations doesn't matter here, you cannot actually *use* these values for anything important, they're purely for display purposes, so using floats and `toFixed` is fine. – user229044 May 09 '18 at 12:08

3 Answers3

3

For e-commerce applications and financial calculations, you should scale up your decimal values by a consistent multiplier and represent all monetary values as integers. This is to avoid the nuances with floating-point math. In JavaScript we only have the floating-point data type for numeric values, but luckily integer math under the floating-point data-type is exact. Therefore converting monetary values to integers (e.g., 2550 cents instead of 25.50 dollars) resolves the issue.

Elliot B.
  • 17,060
  • 10
  • 80
  • 101
  • This is how you overcome IEEE 754 representation – overexchange May 09 '18 at 01:05
  • Can you bold this: *integer arithmetic in floating-point is exact*? – overexchange May 09 '18 at 01:07
  • Can you generalise your answer for any currency? By saying lowest unit of money. I think, 100 is not standard for all currencies – overexchange May 09 '18 at 01:13
  • 1
    You are correct @overexchange. I believe this solution has multi-currency implications: "This has a notable problem – not all currencies in the world are actually decimal (Mauritiana). Also, there are currencies in the world where there are no subunits (Japanese Yen) or non-100 subunits (Jordanian Dinars), or more than one subunit (Chinese Renminbi). Eventually, you’d just recreate the floating point – probably poorly too." - https://modernweb.com/what-every-javascript-developer-should-know-about-floating-points/ – William Fleming May 09 '18 at 01:15
  • @overexchange Good point, I'll modify my answer to take into account other currencies. – Elliot B. May 09 '18 at 01:23
  • In terms of contract, do we transmit integers to backend? – overexchange May 09 '18 at 01:30
  • @overexchange In what format you transmit the numbers to the backend depends on a lot of things -- including whether or not the backend language supports a decimal data type. That's probably an answer for a different StackOverflow question though. – Elliot B. May 09 '18 at 01:33
0

I am doing like this in my project. You can just use .toFixed()

let price = 0.7; // $
let discountPrice = 0.6; // $

let netPrice = (price - discountPrice).toFixed(1);

console.log(netPrice); // correct answer

Also check my answer here: https://stackoverflow.com/a/50056569/631803

Math.round() will not work correctly, so go with .toFixed().

Vikasdeep Singh
  • 20,983
  • 15
  • 78
  • 104
0

I have 2 suggestions:

1. use toPrecision() function to truncate the float number

If you don't want big changes to your code, you can try this function:

function truncate(number) {
    return (parseFloat(number).toPrecision(2));
}

2. always use the smallest unit of the money for ecommerce calculation

E.g. 0.7 dollar = 70 cents, 0.6 dollar = 60 cents

So, 0.7 dollar - 0.6 dollar = 70 cents - 60 cents = 10 cents. // will give you precise value

yellowB
  • 2,900
  • 1
  • 16
  • 19