JS calculation issues

Otokiru

Arch-Supremacy Member
Joined
Nov 16, 2008
Messages
17,150
Reaction score
2,037
Can someone explain huai JS calculation sometimes returning long float, sometimes return as per expectation?
Example:
10.00+4.10 // Returns correctly
10.10+4.10 // Returns correctly
10.20+4.10 // Returns 14.299999999999999
10.30+4.10 // Returns correctly
10.40+4.10 // Returns correctly
10.50+4.10 // Returns correctly
10.70+4.10 // Returns 14.799999999999999
10.80+4.10 // Returns correctly
10.90+4.10 // Returns correctly

Also, what are the best practice when performing calculations to avoid this random long floats which will result in wrong calculation...
 

davidktw

Arch-Supremacy Member
Joined
Apr 15, 2010
Messages
13,547
Reaction score
1,299
Can someone explain huai JS calculation sometimes returning long float, sometimes return as per expectation?
Example:
10.00+4.10 // Returns correctly
10.10+4.10 // Returns correctly
10.20+4.10 // Returns 14.299999999999999
10.30+4.10 // Returns correctly
10.40+4.10 // Returns correctly
10.50+4.10 // Returns correctly
10.70+4.10 // Returns 14.799999999999999
10.80+4.10 // Returns correctly
10.90+4.10 // Returns correctly

Also, what are the best practice when performing calculations to avoid this random long floats which will result in wrong calculation...
CS101
https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems
Are you not aware of floating point representation contain inaccuracy due to fixed size representation limit ? No matter how many bits you assigned to a float point value, 32, 64, or even 128, it will never represent 1/3 accurately. In fact, there will be some values that will not be represented correctly because of how floating points are designed. Eg: 0.1
Read this https://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/

That is why one should never use exact equality when testing for floating point values.

JavaScript:
// never do this
if (float_value == 0.1) {

// one possible approach
if (abs(float_value - 0.1) < epsilon) { //epsilon = Number.EPSILON
  //epsilon is your tolerance
}

// others (depending on what you are testing)
if (float_value <= 0.1) { .. }
if (float_value >= 0.1) { .. }

Read this https://en.wikipedia.org/wiki/Machine_epsilon

You can choose to compute your accumulation using integers instead and only perform the division later when you finally require the value for use. All intermediate calculations, store them as integers so that cumulative errors can be avoided

JavaScript:
let v= 1020+410;
console.log(v / 100); // 14.3
console.log((v / 100).toPrecision(100)); // 14.30000000000000071054273576010018587112426757812500000000000000000000000000000000000000000000000000
console.log((v / 100).toFixed(2)); // 14.30

The floating point representation errors will always exist once you convert into floating point (depending on the number to be represented)
If it is for display purpose, perform your rounding on display to the nearest floating point place.

Say in the case of
JavaScript:
(10.20+4.10).toPrecision(100) // 14.29999999999999893418589635984972119331359863281250000000000000000000000000000000000000000000000000
(10.20+4.10).toFixed(2) // 14.30
 
Last edited:

Otokiru

Arch-Supremacy Member
Joined
Nov 16, 2008
Messages
17,150
Reaction score
2,037
Thanks for the info @davidktw

However, toFixed(2) returns back as a string. If i have more logic below the calculation (e.g: minus rebate -> minus discount -> add tax -> add deposit), then unnecessarily i need to convert it back to float after doing toFixed(2) which will cause an overhead...

Also, in my past experience, I've dealt with toFixed(2) also returning wrong calculation, e.g:
(1.005).toFixed(2) // Returns 1.00
I know the fix for this is to roundup the number, but that will result in another overhead...

And just because of the 2 fail test case out of the 10, now all 10 test case will need to go through this kind of "decimal cleansing process"... is this really the only way?
 

davidktw

Arch-Supremacy Member
Joined
Apr 15, 2010
Messages
13,547
Reaction score
1,299
Thanks for the info @davidktw

However, toFixed(2) returns back as a string. If i have more logic below the calculation (e.g: minus rebate -> minus discount -> add tax -> add deposit), then unnecessarily i need to convert it back to float after doing toFixed(2) which will cause an overhead...

Also, in my past experience, I've dealt with toFixed(2) also returning wrong calculation, e.g:
(1.005).toFixed(2) // Returns 1.00
I know the fix for this is to roundup the number, but that will result in another overhead...

And just because of the 2 fail test case out of the 10, now all 10 test case will need to go through this kind of "decimal cleansing process"... is this really the only way?
Like I have replied you, you only do the rounding during display. Floating point representation error can only be mitigated, not removed.

Javascript uses double precision for floating point, that is 64bits. You can find 3rd “big float” representatation, but as long as the technique is based on floating point, this inherent issue will exist.

If the system cannot even represent a simple 0.1 accurately in the system, 0.1 + 0.1 will never be exactly 0.2 in a discrete system.

You should not test in exactness to a float point value. I have already shown you how to manage tolerance. Read up those articles that I have shared in the previous post.

If you are not doing any division, only addition, subtraction and multiplication, then compute the cents instead of dollars. Then it will all be integral calculations instead of floating point calculation. With native 64bits long, ur max will be (2^63)-1 cents or “infinitely” large if you want to use BigInteger implementations.

I just don’t see why you need to do that, but you could.

:)
 
Last edited:

davidktw

Arch-Supremacy Member
Joined
Apr 15, 2010
Messages
13,547
Reaction score
1,299
Observe the output of this javascript demo and be aware of the danger.
What is shown is not necessarily the same as what is stored.
Open the jsfiddle in a separate window/tab to observe what is printed in the console.
Be aware of what you are trying to compare, the display value or the actual value of the data

Wj3eCjl.png
 
Last edited:

Azzizz81

Suspended
Joined
May 4, 2001
Messages
49,377
Reaction score
2,288
TS, u may want to see if there are libraries that help you deal with the representation and operation where high precision is required. Eg https://www.npmjs.com/package/js-big-decimal

Additionally, you need to determine what is the business requirement when rounding is required. Sometimes there are very specific requirements, eg in the case of payment systems some may require intermediate operations to be in 4 decimal places, before rounding end results to 2
 

davidktw

Arch-Supremacy Member
Joined
Apr 15, 2010
Messages
13,547
Reaction score
1,299
TS, you may always use 3rd party libraries as what is suggested in the post above. Make sure you know the cost involved.

Code:
https://www.measurethat.net/Benchmarks/Show/12367/0/bignumberjs-vs-bigjs-vs-decimaljs-i

You have to understand if it is absolutely necessary to engage the use of Big* number design system in the first place, or it is something floating point system would already be sufficient. Otherwise BigInteger and BigDecimal would be de-facto standards onto how systems will have implemented number systems in automata.

No free lunch here :)

If you even consider rounding is an overhead which I can assure you it is negligible in comparison to the alternatives, then you need to consider if absolute precision is necessary for the performance might not impress you. Even at 1 million operations, the precision has yet to deviate to the point where the rounding cannot handle. So do understand your business requirement before you make a decision.
Here is a simple demo to illustrate my point


There are also non-standard floating point 128bits library at your disposal. Larger bits space representation simply delay the precision deviation for which 10M float64 will have accuracy problem which float 128 will allow even more operations before that happens. (https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format)

https://github.com/munrocket/double.js

KGi8zU7.png
 
Last edited:

Trader11

Banned
Joined
Oct 14, 2018
Messages
15,698
Reaction score
5,233
CS101
https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems
Are you not aware of floating point representation contain inaccuracy due to fixed size representation limit ? No matter how many bits you assigned to a float point value, 32, 64, or even 128, it will never represent 1/3 accurately. In fact, there will be some values that will not be represented correctly because of how floating points are designed. Eg: 0.1
Read this https://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/

That is why one should never use exact equality when testing for floating point values.

JavaScript:
// never do this
if (float_value == 0.1) {

// one possible approach
if (abs(float_value - 0.1) < epsilon) { //epsilon = Number.EPSILON
  //epsilon is your tolerance
}

// others (depending on what you are testing)
if (float_value <= 0.1) { .. }
if (float_value >= 0.1) { .. }

Read this https://en.wikipedia.org/wiki/Machine_epsilon

You can choose to compute your accumulation using integers instead and only perform the division later when you finally require the value for use. All intermediate calculations, store them as integers so that cumulative errors can be avoided

JavaScript:
let v= 1020+410;
console.log(v / 100); // 14.3
console.log((v / 100).toPrecision(100)); // 14.30000000000000071054273576010018587112426757812500000000000000000000000000000000000000000000000000
console.log((v / 100).toFixed(2)); // 14.30

The floating point representation errors will always exist once you convert into floating point (depending on the number to be represented)
If it is for display purpose, perform your rounding on display to the nearest floating point place.

Say in the case of
JavaScript:
(10.20+4.10).toPrecision(100) // 14.29999999999999893418589635984972119331359863281250000000000000000000000000000000000000000000000000
(10.20+4.10).toFixed(2) // 14.30
Which CS101? Never see this before
 

davidktw

Arch-Supremacy Member
Joined
Apr 15, 2010
Messages
13,547
Reaction score
1,299
Which CS101? Never see this before
Computer Science Generic 101

Integer Representation (Sign-Magnitude, 1's complement, 2's complement, why 2's complement is used today vs the other 2, signed vs unsigned representation (discussed with respect with programming languages, not all have unsigned integer data type. Eg: Java only supported signed integer data type, while C/C++ have "unsigned" keyword to declare unsigned datatype, which will affect how bits shifting works)

Floating Point Representation (IEEE Standard 754) Single Precision, Double Precision (concepts of Mantissa, Exponents, Normalisation, conversion from decimal to binary and vice versa, it's advantage vs Fixed Point Representation)

In specific to fixed/floating point representation, why some values are never going to be properly represented in machines (simply discrete vs continuous), and how they occur and thus what is the appropriate way to perform equality check with floating point values.

These are taught in a Computer Architecture course and also at times explained in a programming language course. Study your CS101 rigorously, so that mistake shown below can be avoided.
Code:
if (float_value == 0.1) { ... }



Even the answer provided by me above is not entirely correct, but this was what was taught to us. There are always more correct answers where jobs that require great accuracy will search for.
Feel free to read up https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

If you are one whom does any form of graphics development, dealing with floating points is unavoidable. Speed matters so understanding how hardware implementation works is necessary, The topic on this can be rather daunting, but like I say, it takes a lifetime to polish your craft.

:)

Here is an actual Stanford University lecture PPT found online. Read it if you are interested
CS 106A Lecture Slideshttps://web.stanford.edu › lectures › Lecture10
 
Last edited:
Important Forum Advisory Note
This forum is moderated by volunteer moderators who will react only to members' feedback on posts. Moderators are not employees or representatives of HWZ Forums. Forum members and moderators are responsible for their own posts. Please refer to our Community Guidelines and Standards and Terms and Conditions for more information.
Top