Hướng dẫn precision in javascript float
From the Floating-Point Guide: Show
Note that the first point only applies if you really need specific precise decimal behaviour. Most people don't need that, they're just irritated that their programs don't work correctly with numbers like 1/10 without realizing that they wouldn't even blink at the same error if it occurred with 1/3. If the first point really applies to you, use BigDecimal for JavaScript, which is not elegant at all, but actually solves the problem rather than providing an imperfect workaround.
Mike 22.5k14 gold badges73 silver badges85 bronze badges answered Aug 9, 2010 at 12:30
Michael BorgwardtMichael Borgwardt 338k77 gold badges473 silver badges708 bronze badges 21 I like Pedro Ladaria's solution and use something similar.
Unlike Pedros solution this will round up 0.999...repeating and is accurate to plus/minus one on the least significant digit. Note: When dealing with 32 or 64 bit floats, you should use toPrecision(7) and toPrecision(15) for best results. See this question for info as to why.
answered Sep 4, 2010 at 23:00
linux_mikelinux_mike 2,4031 gold badge16 silver badges3 bronze badges 12 For the mathematically inclined: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html The recommended approach is to use correction factors (multiply by a suitable power of 10 so that the arithmetic happens between integers). For example, in the case of
A (very quick) solution looks something like:
In this case:
I definitely recommend using a tested library like SinfulJS answered Sep 20, 2013 at 2:55
SheetJSSheetJS 21.7k12 gold badges63 silver badges75 bronze badges 8 Are you only performing multiplication? If so then you can use to your advantage a neat secret about decimal arithmetic. That is that answered Aug 11, 2010 at 14:33
Nate ZauggNate Zaugg 4,1422 gold badges35 silver badges51 bronze badges 7 Surprisingly, this function has not been posted yet although others have similar variations of it. It is from the MDN web docs for
UPDATE: Aug/20/2019 Just noticed this error. I believe it's due to a floating point precision error with
These conditions work correctly:
Fix:
This just adds a digit to the right when rounding decimals. MDN has updated the
zhulien 4,4343 gold badges16 silver badges32 bronze badges answered Apr 9, 2018 at 9:30
4 I'm finding BigNumber.js meets my needs.
It has good documentation and the author is very diligent responding to feedback. The same author has 2 other similar libraries: Big.js
and Decimal.js
Here's some code using BigNumber:
Cerbrus 67.5k18 gold badges128 silver badges141 bronze badges answered Dec 2, 2014 at 14:35
Ronnie OverbyRonnie Overby 44k72 gold badges265 silver badges345 bronze badges 2 You are looking for an Try javascript-sprintf, you would call it like this:
to print out your number as a float with two decimal places. You may also use Number.toFixed() for display purposes, if you'd rather not include more files merely for floating point rounding to a given precision.
erik258 12.2k2 gold badges25 silver badges28 bronze badges answered Aug 6, 2010 at 8:38
DouglasDouglas 35.6k8 gold badges73 silver badges89 bronze badges 3
---or---
---also---
--- as in ---
answered Aug 8, 2010 at 3:16
shawndumasshawndumas 1,37314 silver badges17 bronze badges 2 This function will determine the needed precision from the multiplication of two floating point numbers and return a result with the appropriate precision. Elegant though it is not.
answered Aug 8, 2010 at 3:35
GabrielGabriel 18k2 gold badges36 silver badges43 bronze badges 1 You can use
gion_13 40.7k10 gold badges96 silver badges107 bronze badges answered Mar 4, 2015 at 13:49
SoftwareddySoftwareddy 7011 gold badge7 silver badges9 bronze badges You just have to make up your mind on how many decimal digits you actually want - can't have the cake and eat it too :-) Numerical errors accumulate with every further operation and if you don't cut it off early it's just going to grow. Numerical libraries which present results that look clean simply cut off the last 2 digits at every step, numerical co-processors also have a "normal" and "full" lenght for the same reason. Cuf-offs are cheap for a processor but very expensive for you in a script (multiplying and dividing and using pov(...)). Good math lib would provide floor(x,n) to do the cut-off for you. So at the very least you should make global var/constant with pov(10,n) - meaning that you decided on the precision you need :-) Then do:
You could also keep doing math and only cut-off at the end - assuming that you are only displaying and not doing if-s with results. If you can do that, then .toFixed(...) might be more efficient. If you are doing if-s/comparisons and don't want to cut of then you also need a small constant, usually called eps, which is one decimal place higher than max expected error. Say that your cut-off is last two decimals - then your eps has 1 at the 3rd place from the last (3rd least significant) and you can use it to compare whether the result is within eps range of expected (0.02 -eps < 0.1*0.2 < 0.02 +eps). answered Aug 6, 2010 at 8:30
ZXXZXX 4,63426 silver badges35 bronze badges 3 Notice that for the general purpose use, this behavior is likely to be acceptable.
you can define a custom compare function, like this :
Source : http://2ality.com/2015/04/numbers-math-es6.html#numberepsilon answered Sep 15, 2017 at 23:44
user10089632user10089632 4,8381 gold badge24 silver badges34 bronze badges 1 The round() function at phpjs.org works nicely: http://phpjs.org/functions/round
answered Mar 1, 2012 at 19:50
TomTom 1271 silver badge2 bronze badges 1 decimal.js, big.js or bignumber.js can be used to avoid floating-point manipulation problems in Javascript:
link to detailed comparisons
Joe Coder 4,41829 silver badges40 bronze badges answered Aug 6, 2019 at 22:26
Erikas PliaukstaErikas Pliauksta 1,3321 gold badge13 silver badges22 bronze badges 1 The result you've got is correct and fairly consistent across floating point implementations in different languages, processors and operating systems - the only thing that changes is the level of the inaccuracy when the float is actually a double (or higher). 0.1 in binary floating points is like 1/3 in decimal (i.e. 0.3333333333333... forever), there's just no accurate way to handle it. If you're dealing with floats always expect small rounding errors, so you'll also always have to round the displayed result to something sensible. In return you get very very fast and powerful arithmetic because all the computations are in the native binary of the processor. Most of the time the solution is not to switch to fixed-point arithmetic, mainly because it's much slower and 99% of the time you just don't need the accuracy. If you're dealing with stuff that does need that level of accuracy (for instance financial transactions) Javascript probably isn't the best tool to use anyway (as you've want to enforce the fixed-point types a static language is probably better). You're looking for the elegant solution then I'm afraid this is it: floats are quick but have small rounding errors - always round to something sensible when displaying their results. answered Aug 9, 2010 at 8:57
KeithKeith 145k75 gold badges294 silver badges418 bronze badges 0.6 * 3 it's awesome!)) For me this works fine:
Very very simple)) answered Feb 12, 2015 at 9:14
4 To avoid this you should work with integer values instead of floating points. So when you want to have 2 positions precision work with the values * 100, for 3 positions use 1000. When displaying you use a formatter to put in the separator. Many systems omit working with decimals this way. That is the reason why many systems work with cents (as integer) instead of dollars/euro's (as floating point). answered Aug 9, 2010 at 12:12
GertjanGertjan 8526 silver badges9 bronze badges not elegant but does the job (removes trailing zeros)
answered Sep 22, 2009 at 12:43
PeterPeter 5,0485 gold badges28 silver badges38 bronze badges 1 Problem Floating point can't store all decimal values exactly. So when using floating point formats there will always be rounding errors on the input values. The errors on the inputs of course results on errors on the output. In case of a discrete function or operator there can be big differences on the output around the point where the function or operator is discrete. Input and output for floating point values So, when using floating point variables, you should
always be aware of this. And whatever output you want from a calculation with floating points should always be formatted/conditioned before displaying with this in mind.
These 2 things are usually not done and in most cases the differences caused by not doing them are too small to be important for most users, but I already had a project where output wasn't accepted by the users without those corrections. Discrete functions or operators (like modula) When discrete operators or functions are
involved, extra corrections might be required to make sure the output is as expected. Rounding and adding small corrections before rounding can't solve the problem. Better avoid having the problem It is often more efficient to avoid these problems by using data types (integer or fixed point formats) for calculations like this which can store the expected input without rounding errors. An example of that is that you should never use floating point values for financial calculations. answered Jul 27, 2017 at 14:04
Elegant, Predictable, and ReusableLet's deal with the problem in an elegant way reusable way. The following seven lines will let you access the floating point precision you desire on any number simply by appending
Cheers! answered Sep 12, 2019 at 6:41
BernestoBernesto 1,18114 silver badges18 bronze badges 6 Solved it by first making both numbers integers, executing the expression and afterwards dividing the result to get the decimal places back:
Results for several
operations (the excluded numbers are results from
answered Sep 29, 2019 at 17:53
SimonSimon 2,4771 gold badge30 silver badges40 bronze badges From my point of view, the idea here is to round the fp number in order to have a nice/short default string representation.
Then, as far as I understand, we can round the value up to 15 digits to keep a nice string representation.
eg.
The function would be:
answered Nov 29, 2019 at 10:55
Franck FreiburgerFranck Freiburger 24.5k20 gold badges67 silver badges95 bronze badges 2 Have a look at Fixed-point arithmetic. It will probably solve your problem, if the range of numbers you want to operate on is small (eg, currency). I would round it off to a few decimal values, which is the simplest solution. answered Sep 22, 2009 at 7:39
MariusMarius 56.4k31 gold badges126 silver badges147 bronze badges 1 You are right, the reason for that is limited precision of floating point numbers. Store your rational numbers as a division of two integer numbers and in most situations you'll be able to store numbers without any precision loss. When it comes to printing, you may want to display the result as fraction. With representation I proposed, it becomes trivial. Of course that won't help much with irrational numbers. But you may want to optimize your computations in the way they will cause the least problem (e.g. detecting situations like answered Aug 7, 2010 at 11:21
skaleeskalee 11.8k6 gold badges50 silver badges56 bronze badges 1 I had a nasty rounding error problem with mod 3. Sometimes when I should get 0 I would get .000...01. That's easy enough to handle, just test for <= .01. But then sometimes I would get 2.99999999999998. OUCH! BigNumbers solved the problem, but introduced another, somewhat ironic, problem. When trying to load 8.5 into BigNumbers I was informed that it was really 8.4999… and had more than 15 significant digits. This meant BigNumbers could not accept it (I believe I mentioned this problem was somewhat ironic). Simple solution to ironic problem:
answered Dec 14, 2014 at 17:34
mcgeo52mcgeo52 511 silver badge7 bronze badges 0
answered May 8, 2015 at 11:22
Avoid dealing with floating points during the operation using IntegersAs stated on the most voted answer until now, you can work with integers, that would mean to multiply all your factors by 10 for each decimal you are working with, and divide the result by the same number used. For example, if you are working with 2 decimals, you multiply all your factors by 100 before doing the operation, and then divide the result by 100. Here's an example, Result1 is the usual result, Result2 uses the solution:
The third result is to show what happens when using parseFloat instead, which created a conflict in our case. answered Sep 21, 2019 at 18:34
DavidTaubmannDavidTaubmann 3,0742 gold badges32 silver badges43 bronze badges 1 I could not find a solution using the built in
This uses the known smallest difference between 1 and the smallest floating point number greater than one to fix the
Maximum precision is answered Jun 15, 2021 at 13:15
KarlssonKarlsson 1932 silver badges13 bronze badges 1 Try my chiliadic arithmetic library, which you can see here. If you want a later version, I can get you one. answered Oct 6, 2009 at 0:04
Robert LRobert L 1,9632 gold badges13 silver badges11 bronze badges 1 |