Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Very large numbers #15

Closed
limbero opened this issue Jun 12, 2013 · 14 comments
Closed

Very large numbers #15

limbero opened this issue Jun 12, 2013 · 14 comments

Comments

@limbero
Copy link

limbero commented Jun 12, 2013

It appears that the handling of very large numbers is suboptimal. "5^5^5" (or "5^3125") is evaluated as infinity, for example. I am aware that it's a huge number, "1.911012597945477520356404559703964599198081048 × 10^2184", but still, it seems to me like it should just respond with "Error: Too big number" or something like that. Preferably without breaking the infinity evaluation of things like division with zero.

You'll probably be seeing much of me here since I just built a little something using Math.js here. I might also start contributing to this project in the future. I'd like to take the chance to say that I really love this library and am very grateful for its existence before you start seeing me as an annoying nitpicker. Thanks!

@josdejong
Copy link
Owner

constructive input is always welcome :)

math.js cannot work with very large numbers as it just uses JavaScript's Numbers, which are floating point numbers, which have a finite range and precision. When out of range, a number will get the value Infinity or -Infinity. That is how floating point numbers work in any language as far as I know.

To be able to work with large numbers, we shouldn't use floating point numbers but use a special BigNumber data type. This feature is planned to be added, see roadmap.

If you really want to give your users an error message "Too big number" instead of returning Infinity, you can of course replace infinity output with an error message.

@husayt
Copy link

husayt commented Oct 25, 2013

Here are some other JS Big Number libraries, which could be used for reference:

This is such a major issue, that for time being math.js could just wrap around one of these libraries, until there is dedicated implementation.

@josdejong
Copy link
Owner

Thanks. Maybe it's just fine to integrate an existing library by wrapping around it? Even easier. (Unless there is a serious performance penalty)

@husayt
Copy link

husayt commented Oct 26, 2013

wrapper idea is really interesting. we could have wrappers around standard js number, and some other bigNumber implementations (by using adapter pattern maybe). One could switch them via options. If performance would be a issue for particular problem user could switch to standard js number. Additional plus, this will also make it easier to integrate mathjs's own bignumber implementation in future and still allow users to switch to previous behavior.

@diversario
Copy link

MikeMcl's BigNumber library looks rather good, has tests and everything.

@josdejong
Copy link
Owner

Wohooo, check out the latest develop branch. I've started integrating the bignumber.js library in math.js. See examples and docs.

var mathjs = require('../index'),
    math = mathjs({
      number: {
        defaultType: 'bignumber' // Choose from: 'number' (default), 'bignumber'
      }
    });

math.eval('0.1 + 0.2');  // BigNumber, 0.3
math.eval('0.3 / 0.2');  // BigNumber, 1.5

@josdejong
Copy link
Owner

A question that arises now is the following: Only arithmetic functions have support for big numbers now. If the expression parser parses all numbers as BigNumber, it will fail on non-arithmetic functions:

var mathjs = require('../index'),
    math = mathjs({
      number: {
        defaultType: 'bignumber' // Choose from: 'number' (default), 'bignumber'
      }
    });

math.eval('0.1 + 0.2');  // BigNumber, 0.3
math.eval('0.3 / 0.2');  // BigNumber, 1.5

math.eval('sin(0.1)');   // ERROR!

How to deal with that?...

@husayt
Copy link

husayt commented Nov 17, 2013

Hi Jos,
this is terrific news. I am so excited about this and you made a very good choice with BigNumber.js as it is being actively developed.

As for the question, I can a suggest few ideas:

  • for each function have a accepted params type list. Then you could "downgrade" to standard number if the function doesn't support bignumbers. This (effectively maintaining meta data about each function) could be used for some other cool things ahead
  • just have an array of functions supporting bignumbers and use bignumber if one of these functions involved, otherwise do downgrade. This is quicker way of implementing first solution.
  • (and finally. not serious, but the optimal one ) add bigNumber support to all these functions. ;-))))))

@guillermobox
Copy link
Contributor

Hello,

regarding to this problem of not having the trigonometrical functions available (and possibly others), I think there are possible solutions, similar to the previously commented by husayt.

  • Downgrade the number to a standard number, and then calculate using the built-in library. The problem is that the input of the function will be a big number, and the output a standard number (or, if you make a cast, a big number but with less precision). This is, I think, something really bad and should be announced in the documentation if you do it.
  • Calculate the function by yourself, and when the function gets implemented in big number by another developer (or you), change your previous calculation for the big number one. This works like a temporary patch, but will give you the right answer and allows you to work with big numbers all the way from the beginning.

If you want to implement the second one (which I think is the best one), in the particular case of the trigonometrical functions is very easy. Just take into consideration that the trigonometrical functions have a given periodicity (0, 2*pi), so you should reduce the input argument to a small number. Now, you need a polynomial expansion of the sin function, which you can make yourself using the Taylor Series, for example: http://en.wikipedia.org/wiki/Taylor_series. As long as you can make multiplications and additions, you can represent any function using polynomials. The Taylor series are only one of the multiple possible choices, there are others, with better convergency and other properties.

This will be a little slow, BTW, because instead of calculating a sine, you calculate a (maybe big) polynomial. But don't despair, that's how this things are done in other libraries, along with other techniques to be faster (like look-up table combined with interpolation and series). If you are dealing with arbitrary precission, this is the way to go.

My Summary: implement a slow-but-accurate first solution, wait until a full library call is available in BigNumber and meanwhile tell the customers in the documentation that some functions are going to be slow but accurate (which, BTW, would be the case even if BigNumber implements those functions).

@josdejong
Copy link
Owner

Yes, in the end all functions should support bignumbers :). Maybe there is a Java or C implementation which we can port to JavaScript.

Until then we need a temporary solution. I think indeed that downgrading to a regular Number is best. When output is a Number instead of a BigNumber you get a clue that the function wasn't able to calculate with high precision.

@guillermobox
Copy link
Contributor

But how can you downgrade a number from BigNumber to a regular Number? In some cases you can (when the number is small), but the range of Number is not enough to take all the cases, like in 5^5^5. So if the user wants to calculate sin(5^5^5), you will now again have the same problem as before: the number is too large.

At least in the case of trigonometrical functions, you can reduce the number to the range of [0, 2*pi] before calculating it, so the problem can be solved using the functions provided for Number. I don't know how much mathematical functions you need that are not implemented in BigNumber, and for those functions for sure you don't have the periodicity trick. So I don't know if you are solving the problem.

@josdejong
Copy link
Owner

No, we are not solving the problem by downgrading BigNumbers to Numbers for non-supported functions. It is ugly but at least gives us a solution which works: When only using functions that support BigNumber, you get a BigNumber as output, when using unsupported functions you will get a Number as output. BigNumbers which are too large to fit in a Number will return Infinity.

The problem will solved "for real" when all functions support BigNumber, however I'm afraid that this will be quite some work, too much get this done before the next release at least.

@guillermobox
Copy link
Contributor

Oh, sorry, I didn't catch the "return infinity if the number is too large" part before. Yes, that's a good temporary patch, because the implementation of the full mathematical functions is really expensive in terms of time.

@josdejong
Copy link
Owner

I've released v0.16.0, including BigNumber support! See docs and examples.

We will need to extend BigNumber support to all functions. And It would be great to have a BigComplex and BigUnit types as well in the future.

It's really time to rework the code to a plugin/modular architecture discussed in #71: with this new BigNumber type the amount of manual type checking and type conversion is growing rapidly.

josdejong pushed a commit that referenced this issue Mar 23, 2015
Matrix transpose implementation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants