Java 中的高效 BigInteger
我们的产品中有一组需要 BigInteger 的位置,因为数字可能相当长。然而,在超过 90% 的情况下,它们实际上并没有那么长,可以很容易地包含在 long 中。
看看BigInteger的实现,在Long就足够的情况下使用BigInteger是相当浪费的。
创建一个具有 BigInteger 之类的函数(除法、乘法等)并且由 BigInteger 的子类和包装 Long 的类实现的接口是否有意义?比如:
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)
也许我们的方向错了?
谢谢, 更新
:这些对象(Long 或 BigInteger)会在内存中存储相当长一段时间,因为它们帮助我们识别与之交互的系统的有问题的行为。因此,内存占用可能是一个问题。这是我们试图避免的问题。 BigInteger 类有几个字段(signum、mag 数组、bitcount 等),这些字段加在一起大约是封装 Long 的类的两倍(首先考虑到拥有一个 Object 的内存成本)。这意味着我们经常使用的东西的占地面积增加了一倍。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您必须对这些值进行算术运算吗?因为如果你这样做,那么一开始是 long 的可能会变成 BigInteger,这听起来很痛苦:你必须在每个算术运算之前进行测试,看看它可能会超过 MAX_LONG。好吧,我想你可以将所有这些封装在你的包装类中。与 BigInteger 类循环遍历包含 1 个或 2 个元素的数组所需的时间相比,测试溢出需要多少时间?
如果您不进行算术运算,那么使用 long 节省的成本将是微乎其微的。你用 BigInteger 做什么,只是读入并写出?在这种情况下,几乎肯定不值得这么麻烦。
就我个人而言,这是我自己想做的事情,我理解你的想法。但后来我会退一步说:性能真的是一个问题吗?我们到底做了多少算术?我们会获得多少性能提升?是否值得增加程序的复杂性并可能引入错误?
除非您有理由相信性能确实是一个问题并且这样做会产生重大影响,否则我不会。
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.
我在 1986 年左右为 Cobol 编译器实现了这样的东西。它对性能没有任何影响:决定它是否适合 long,然后将其转换为 long,然后再次返回的开销等于节省的时间。
I implemented exactly such a thing for a Cobol compiler in about 1986. It made no difference to performance whatsoever: the overhead of deciding whether it would fit in a long and then converting it to a long and then back again equalled the time saving.