Comments (13)
Yes, this is intended.
BigNumber.config(10)
is the short form of BigNumber.config({ DECIMAL_PLACES: 10 })
, which specifies that division is to be performed to 10 decimal places.
So, for example, 5e-15 / 3
, which is 0.000000000000001666...
, is 0
when rounded to 10 decimal places (assuming ROUND_HALF_UP
rounding mode).
To do divisions on small values without losing precision just make sure that the DECIMAL_PLACES
is set sufficiently high. For example, if you want 5e-15 / 3
to equal 1.666666667e-15
then it would need to be set to at least 24 (i.e 15 + 9).
Normally, you would just set a higher DECIMAL_PLACES
value then just pass one less than the number of significant digits you want to toExponential
, e.g.
BigNumber.config(30);
new BigNumber('5e-15').div('3').toExponential(9); // '1.666666667e-15'
The ability to perform division to a specified number of significant digits, instead of decimal places, is a feature that will be added soon.
from bignumber.js.
Yes, this is intended.
Ai. I hope you are willing to change your mind on this. The number of decimals should really be independent from the exponent of a number.
I see similar issues with sqrt
and pow
: they seem not to reckon with the configured precision, resulting in numbers loosing digits or having too much digits.
The ability to perform division to a specified number of significant digits, instead of decimal places, is a feature that will be added soon.
Thanks, I'm looking forward to having this issue fixed!
from bignumber.js.
@MikeMcl Thanks for great library.
This whole problem with precision, decimal and exponential points is really tricky.
Maybe you can have a look at the lengthy discussion we had with @josdejong here. At the end we found a solution which allowed us to cover all possible cases. (Thanks @josdejong ) Also this is along with standard JS way of doing precisions and exponentials.
Users of our popular calculator at (http://numerics.info) have very different requirements and current settings allow them to meet whole spectrum of needs. That will work absolutely great, once we get bigNumber.js working.
from bignumber.js.
The number of decimals should really be independent from the exponent of a number.
I am not clear what you mean exactly, or why you believe that.
If a particular number of decimals (in exponential notation) is required then it can be specified as shown above. If a particular number of significant digits is required it can be specified by toPrecision
.
I see similar issues with sqrt and pow: they seem not to reckon with the configured precision, resulting in numbers loosing digits or having too much digits.
The problem with statements such as this is that some viewers may mistakenly believe there is some fault with the library and that it is not working correctly. As I explained, and the README and documentation makes clear, the "configured precision" is in terms of decimal places (of a number in normal, non-exponential notation) not significant digits. sqrt
and pow
(negative exponents) always conform to the required precision in that sense, and numbers never lose or have too many digits.
I'm looking forward to having this issue fixed!
I don't think it's an issue that needs fixing, it's a fundamental design decision. Some people find it simpler to think in terms of decimal places, others in terms of significant digits. Maths homework sometimes required answers in terms of the former, sometimes the latter. Generally, perhaps more scientific use cases prefer significant digits and more financial use cases prefer decimal places. There are advantages and disadvantages to each.
The BigDecimal libraries work in terms of significant digits and there are quite complex rules as to the precision of the result of a calculation. I wanted to take a different, perhaps simpler approach: just one global decimal places setting for operations involving division, and other operations always returning full precision.
But, yes, it would be good to be able to specify precision in terms of significant digits and I am working on that at present as a by-product of adding support for non-integer powers.
Thanks for the feedback.
from bignumber.js.
I understand your point. However to me this is a serious flaw, not a feature.
What I would expect from a BigNumber library is to handle (a) very large numbers, (b) very small numbers, and (c) with an arbitrary (configurable) precision. Unfortunately bignumber.js only does (c) so far.
The design decision to handle precision like fixed point means that you effectively can't work with very small numbers, as you loose precision below DECIMAL_PLACES
. And you can't efficiently work with very large numbers as all decimals are stored sort of as a fixed point number (new BigNumber('1e500').div(3)
stores the number with 520 digits (!)). I would like BigNumber to work as a floating point number, storing a limited (configured) number of significant digits, independent from the exponent of the number. I don't think this would harm these "some people", as the can just set DECIMAL_PLACES
very high and use .toFixed(xyz)
to get output in their desired number-of-decimals-behind-the-point.
The following type of calculations should just be no problem for BigNumber with 20 digits, like it is no problem for a regular (floating point) Number with ~16 digits precision.
console.log(5e-30 / 3); // 1.6666666666666666e-30
console.log(new BigNumber('5e-30').div(3).valueOf()); // 0
console.log(Math.sqrt(3e-30)); // 1.7320508075688773e-15
console.log(new BigNumber('3e-30').sqrt().valueOf()); // 0
from bignumber.js.
Those calculations are no problem for this library. It doesn't seem unreasonable to have to set the DP (decimal places) to 30 or 40 (depending on how many SD (significant digits) you want) when working with numbers such as 5e-30
. The numbers are stored in floating point format so it is not inefficient to work with small numbers using a high DP.
What I would expect from a BigNumber library is to handle (a) very large numbers, (b) very small numbers, and (c) with an arbitrary (configurable) precision. Unfortunately bignumber.js only does (c) so far.
Well, it does all three, but clearly not as you would like.
The design decision to handle precision like fixed point means that you effectively can't work with very small numbers, as you loose precision below DECIMAL_PLACES.
Yes, but only in the same way that you can lose precision when performing division to an arbitrary number of SD if you set the value too low
precision = 10 (significant digits)
1e+30 / 3 = 333333333300000000000000000000 // Incorrect by more than 33333333333333333333
decimal places = 10
1e+30 / 3 = 333333333333333333333333333333.3333333333
As shown, it is easier to lose precision with large numbers when it is specified in terms of SD, and as larger numbers are arguably more commonly used than extremely small numbers, it follows that it is easier to avoid losing precision using DP than SD.
And you can't efficiently work with very large numbers as all decimals are stored sort of as a fixed point number (new BigNumber('1e500').div(3) stores the number with 520 digits (!)).
Yes, but 1e500
is not just a big number, it is an enormous number (for example, the estimated number of atoms in the universe is 1e+80
).
And if you want to store and use fewer SD you can do
new BigNumber( BigNumber('1e500').div(3).toPrecision(20) )
although I accept that this is inefficient and that is why I'm adding better support for SD.
As it is, this library is best used for numbers of a few hundred digits and less, and perhaps when decimal places are more important than significant digits (as in, for example, financial calculations). The priority is not to be able to efficiently handle enormous/tiny values that most users of the library will not be using.
from bignumber.js.
This is indeed the best choice for financial calculations and less for scientific calculations. Reading the docs, the setting DECIMAL_PLACES
is only applied by div
, sqrt
, and pow
, so they are the only ones who can suffer loosing precision. Maybe you can introduce a complementary setting like MINIMUM_SIGNIFICANT_DIGITS
to prevent that :D.
Anyway, I agree with you that this is kind of an edge case. I'm looking forward to your improvements for division (and sqrt, pow as well?). Thanks for this excellent and well documented library.
from bignumber.js.
Hi Jos,
I have just published decimal.js which handles precision in terms of significant digits. It was going to be an update to bignumber.js, but I made so many changes I thought I better release it as a new library.
from bignumber.js.
That's awesome Michael! I'm going to check it out asap.
from bignumber.js.
@MikeMcl does this explain why new BigNumber('1.1').dividedBy('2').times(new BigNumber(2).dividedBy('1.1')).toString()
returns 1.000000000000000000001
and not 1
?
from bignumber.js.
2 / 1.1
has a non-terminating decimal expansion (an infinite number of digits after the decimal point), which means that the result of BigNumber(2).dividedBy(1.1)
will only be an approximation.
BigNumber.config().DECIMAL_PLACES // 20
BigNumber.config().ROUNDING_MODE // 4
new BigNumber(2).dividedBy(1.1) // 1.81818181818181818182
BigNumbers are stored as floating-point values not ratios.
from bignumber.js.
Ok, so because BigNumbers are stored as floating-point and not ratios, then the lib is unable to cancel the ratios and return exactly 1
, correct? In that case, should the number of DECIMAL_PLACES
be increased in order to cover the necessary precision? Is this what decimal.js does? (edit: reading about it here - MikeMcl/big.js#45)
from bignumber.js.
Infinite precision would be needed in order to return exactly 1
.
decimal.js works using significant digits instead of decimal places, but it also stores numbers in a floating-point format.
Your choices would seem to be to either find a library that stores numbers as ratios or just round the result.
a = new BigNumber(1.1).dividedBy(2)
b = new BigNumber(2).dividedBy(1.1)
a.times(b).round() // 1
a.times(b).round(10) // 1
a.times(b).round(19) // 1
a.times(b).round(20) // 1
a.times(b).round(21) // 1.000000000000000000001
from bignumber.js.
Related Issues (20)
- Using version 9.1.1, run new BigNumber(0).exponentiatedBy('-12345678901234567890123456789012345678901234567890').valueOf() Is return to infinity normal? HOT 1
- Issue toNumber() function round up when number is too big (v9.1.1) HOT 2
- Division on exponential values leads to infinite loop HOT 3
- 负数加减乘除不好用 HOT 1
- [Feature Request]: Can we support `toBigInt`?
- Type error HOT 2
- Big Number (toFixed,dp,decimalPlaces,toFormat) - Chrome Update Issue 115.0.5790.102 HOT 24
- Minus sign in formatted strings HOT 2
- wrong calculation result on multipliedBy/times methods HOT 1
- toNumber does not respect ROUNDING_MODE HOT 11
- Calculation error HOT 1
- Is there any other way to handle new BigNumber(999999999999999999999) without using strings? HOT 2
- Difference between multipliedBy and dividedBy behaviors HOT 2
- Different result between toFixed and toNumber HOT 1
- Can't convert to Base64 HOT 1
- Tree shake commonjs version from mjs version HOT 1
- toFixed error
- [Bug] Return Type of Methods HOT 1
- Logarithms (I know there is another issue about this)
- toString() default base is not 10? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bignumber.js.