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

BigInt is quite slow in some High-precision operations, such as BigInt.from(1000000000000001).pow(1234567) #53762

Open
835127729 opened this issue Oct 15, 2023 · 3 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-math type-enhancement A request for a change that isn't a bug

Comments

@835127729
Copy link

835127729 commented Oct 15, 2023

my General info:

  • Dart 3.2.0-22.0.dev (dev) (Tue Aug 1 01:03:03 2023 -0700) on "macos_arm64"
  • on macos / Version 13.3.1 (Build 22E261)

As the title metioned, code:
BigInt.from(1000000000000001).pow(1234567);
runs very slowly and won't even stop.

I tested the same case in JAVA using BigDecimal, and it runs slowly too but better than dart do.
BigDecimal.valueOf(1000000000000001).pow(1234567);

Howerver, BigDecimal.pow() has another param called MathContext to set calculation precision, like:
BigDecimal.valueOf(1000000000000001).pow(1234567, MathContext.DECIMAL128);
and then i get the result in an appropriate time.

So my question is should BigInt add a parameter like MathContext

@lrhn
Copy link
Member

lrhn commented Oct 15, 2023

The difference between BigInt and BigDecimal is that the former is an integer, and the latter is an integer and an exponent.
The representation of BigInt 1000000000000001 ** 1234567 has at least 15 * 1234567 decimal digits, or ~60M bits.
That takes a while to compute.

BigDecimal would have the same result if not for the precision restriction, but that only really makes sense for a number with an exponent. Even if BigInt threw away the lower bits, it would still be 60M+ bits.

If you try the similar thing in Java using it's BigInteger, you get similar humongous and somewhat slow results:

import java.math.BigInteger;
class HelloWorld {
    public static void main(String[] args) {
        BigInteger i = new BigInteger("1000000000000001");
        BigInteger p = i.pow(1234567);
        String s = p.toString();
        System.out.println("Digits: " + s.length());
    }
}

@835127729
Copy link
Author

The difference between BigInt and BigDecimal is that the former is an integer, and the latter is an integer and an exponent. The representation of BigInt 1000000000000001 ** 1234567 has at least 15 * 1234567 decimal digits, or ~60M bits. That takes a while to compute.

BigDecimal would have the same result if not for the precision restriction, but that only really makes sense for a number with an exponent. Even if BigInt threw away the lower bits, it would still be 60M+ bits.

If you try the similar thing in Java using it's BigInteger, you get similar humongous and somewhat slow results:

import java.math.BigInteger;
class HelloWorld {
    public static void main(String[] args) {
        BigInteger i = new BigInteger("1000000000000001");
        BigInteger p = i.pow(1234567);
        String s = p.toString();
        System.out.println("Digits: " + s.length());
    }
}

so maybe we need something like BigDecimal in dart?

@lrhn lrhn added area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-math type-enhancement A request for a change that isn't a bug labels Oct 16, 2023
@lrhn
Copy link
Member

lrhn commented Oct 16, 2023

Adding BigDecimal is an option. So is BigFloat.
Both could probably work with a "rounding strategy", to avoid too much precision.

If we ever add such, I'd probably put them into dart:math instead of dart:core. (I'd move BigInt there too if I could.)

It's probably non-trivial to implement such classes in a way that is performant for all operations. Multiplication is cheap, division is tricky (as always, because the precise result can always be infinite at the current base), and addition and subtraction require some shifting around that isn't necessarily free. (For decimal, it's also not just shifting, unless the representation is itself decimal.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-math type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

2 participants