We have a set of locations within our product where BigInteger is required as the numbers can be fairly long. However, in over 90% of the cases, they are actually not that long and can be easily contained with-in a long.
Looking at BigInteger's implementation, it would be quite a waste to use BigInteger where Long is sufficient.
Would it make sense to create an Interface that has functions like BigInteger (divide, multiply, etc.) and that would be implemented by a child class of BigInteger and a class that wraps Long? Something like:
Interface: EfficientBigInteger
Class 1: MyBigInteger extends BigInteger imlpements EfficientBigInteger
Class 2: MyLong implements EfficientBigInteger (this will contain a Long, as we cannot extend the Long class)
Maybe we're in the wrong direction here?
Thanks, Yon
UPDATE: These objects (Long or BigInteger) are stored in memory for quite a while as they help us identify problematic behaviors of systems we interact with. Therefore, the memory footprint could be a problem. This is the problem we're trying to avoid. The BigInteger class has several fields (signum, mag array, bitcount, etc. etc.) which together are roughly double that of a class that encapsulates Long (taking into account the memory costs of having an Object in the first place). It means double the footprint for something we use a lot of.
The standard library BigInteger class in Java is known to be notoriously slow (at least for Java 7 and earlier, and I doubt Java 8 is any different).
The largest primitive data type that can store integer values in Java is the 64-bit long. Given that it is a signed data type, this gives it the range from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. So we already established that BigIntegers are “Big”.
BigInteger provides analogues to all of Java's primitive integer operators, and all relevant methods from java. lang. Math. Additionally, BigInteger provides operations for modular arithmetic, GCD calculation, primality testing, prime generation, bit manipulation, and a few other miscellaneous operations.
BigInteger must support values in the range -2 Integer.MAX_VALUE (exclusive) to +2 Integer.MAX_VALUE (exclusive) and may support values outside of that range. The range of probable prime values is limited and may be less than the full supported positive range of BigInteger . The range must be at least 1 to 2500000000.
Do you have to do arithmetic on these values? Because if you do, then one that starts out as a long may become a BigInteger, and that sounds like a pain: You'd have to precede every arithmetic operation with a test that it might go over MAX_LONG. Well, I suppose you could encasulate all this in your wrapper class. How much time would it take to test for overflow, compared to the time that the BigInteger class takes to loop through an array of 1 or 2 elements?
If you're not doing arithmetic, then the savings by using a long would be minimal. What are you doing with the BigInteger, just reading it in and writing it out? In that case almost surely not worth the trouble.
Personally, this is the sort of thing that I would be tempted to do myself, I understand your thinking. But then I would step back and say: Is performance really a problem here? JUst how much arithmetic are we doing? How much performance gain would we get? Is it worth adding to the complexity of the program and possibly introducing bugs?
Unless you have reason to believe that performance is really a problem and that doing this would make a significant difference, I wouldn't.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With