如何求 Java BigInteger 的平方根?
是否有一个库可以计算 BigInteger 的平方根?我希望它离线计算 - 仅一次,并且不在任何循环内。因此,即使计算成本昂贵的解决方案也是可以的。
我不想找到一些算法并实现。一个现成的解决方案将是完美的。
Is there a library that will find the square root of a BigInteger? I want it computed offline - only once, and not inside any loop. So even computationally expensive solution is okay.
I don't want to find some algorithm and implement. A readily available solution will be perfect.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(20)
只是为了好玩:
Just for fun:
我知道没有图书馆可以解决您的问题。您必须从某个地方导入外部库解决方案。我在下面提供的内容比获取外部库要简单。
您可以使用两个静态方法在类中创建您自己的外部库解决方案,如下所示,并将其添加到您的外部库集合中。这些方法不需要是实例方法,因此它们是静态的,并且方便的是,您不必实例化类即可使用它们。整数平方根的范数是下限值(即小于或等于平方根的最大整数),因此您可能只需要下面类中的一个静态方法,即floor方法来获取下限值,并且可以选择忽略上限(即大于或等于平方根的最小整数)方法版本。现在,它们位于默认包中,但您可以添加包语句将它们放入您认为方便的任何包中。
这些方法非常简单,并且迭代非常非常快地收敛到最接近的整数答案。如果你试图给他们一个否定的论点,他们会抛出一个 IllegalArgumentException 异常。您可以将异常更改为另一种异常,但必须确保负参数引发某种异常或至少不尝试计算。负数的整数平方根不存在,因为我们不在虚数领域。
这些来自众所周知的简单迭代整数平方根算法,这些算法已经在手工计算中使用了几个世纪。它的工作原理是对高估和低估进行平均,以收敛到更好的估计。可以重复这一过程,直到估计值与期望的值接近为止。
它们基于 y1 = ((x/y0) + y0) / 2 收敛到最大整数 yn,其中 yn * yn <= x。
这将为您提供 x 的 BigInteger 平方根 y 的下限值,其中
y*y<=x且(y+1)*(y+1)> x。
调整可以为您提供 x 的 BigInteger 平方根 y 的上限值,其中
y*y>=x且(y-1)*(y-1)< x
两种方法都经过测试并且有效。他们在这里:
I know of no library solution for your question. You'll have to import an external library solution from somewhere. What I give you below is less complicated than getting an external library.
You can create your own external library solution in a class with two static methods as shown below and add that to your collection of external libraries. The methods don't need to be instance methods and so they are static and, conveniently, you don't have to instance the class to use them. The norm for integer square roots is a floor value (i.e. the largest integer less than or equal to the square root), so you may need only the one static method, the floor method, in the class below for the floor value and can choose to ignore the ceiling (i.e. the smallest integer greater than or equal to the square root) method version. Right now, they are in the default package, but you can add a package statement to put them in whatever package you find convenient.
The methods are dirt simple and the iterations converge to the closest integer answer very, very fast. They throw an IllegalArgumentException if you try to give them a negative argument. You can change the exception to another one, but you must ensure that a negatve argument throws some kind of exception or at least doesn't attempt the computation. Integer square roots of negative numbers don't exist since we are not in the realm of imaginary numbers.
These come from very well known simple iterative integer square root algorithms that have been used in hand computations for centuries. It works by averaging an overestimate and underestimate to converge to a better estimate. This may be repeated until the estimate is as close as is desired.
They are based on y1 = ((x/y0) + y0) / 2 converging to the largest integer, yn, where yn * yn <= x.
This will give you a floor value for a BigInteger square root, y, of x where
y * y <= x and (y + 1) * (y + 1) > x.
An adaptation can give you a ceiling value for BigInteger square root, y, of x where
y * y >= x and (y - 1) * (y - 1) < x
Both methods have been tested and work. They are here:
奇怪的是,之前没有人提到过,但在 java 9 中,BigInteger 中有 sqrt,因此您可以像这样使用它:
https://docs.oracle.com/javase/9/docs/api/java/math/BigInteger.html#sqrt--
EDIT-1
添加此函数还有另一种风格,除了取整平方根之外,还返回余数。
Strange that nobody has mentioned it earlier but in java 9 you have sqrt in BigInteger, so you can just use it like that:
https://docs.oracle.com/javase/9/docs/api/java/math/BigInteger.html#sqrt--
EDIT-1
Adding that there is another flavour of this function that, in addition to the floored square root, also returns the remainder.
我无法验证它们的准确性,但在谷歌搜索时有几个自制的解决方案。其中最好的似乎是这个: http ://www.merriampark.com/bigsqrt.htm
还可以尝试 Apache commons Math 项目(一旦 Apache 从 JCP 博客文章后的轰炸中恢复过来)。
I can't verify the accuracy of them but there are several home grown solutions when googling. The best of them seemed to be this one: http://www.merriampark.com/bigsqrt.htm
Also try the Apache commons Math project (once Apache recovers from its bombardment after the JCP blog post).
正如Jigar所述,牛顿迭代 非常容易理解和实现。我将让其他人决定它是否是求数字平方根的最有效算法。
通过递归,只需大约两行即可完成。
其中n是我们要求平方根的数字,x0是上一次调用的数字,当从另一个发起第一次调用时,它总是1方法。所以最好你也用这样的东西来补充它;
As Jigar states, Newton's iteration is both quite simple to understand and to implement. I'll leave it up to others decide whether it is the most efficient algorithm or not for finding the square root of a number.
With recursion it can be done in just about two lines.
Where n is the number we want to find the square root of, and x0 is the number from the previous call, which will always be 1 when initiate the first call from another method. So preferably, you will complement it with something like this as well;
对于初步猜测,我会使用 Math.sqrt(bi.doubleValue()) ,您可以使用已经建议的链接来使答案更加准确。
For an initial guess I would use
Math.sqrt(bi.doubleValue())
and you can use the links already suggested to make the answer more accurate.我需要 BigIntegers 的平方根来实现二次筛选。我在这里使用了一些解决方案,但迄今为止绝对最快和最好的解决方案来自 Google Guava 的 BigInteger 库。
可以找到文档 这里。
I needed to have the square root for BigIntegers for implementing the quadratic sieve. I used some of the solutions here but the absolutely fastest and best solution so far is from Google Guava's BigInteger library.
Documentation can be found here.
另一种方法,相当轻便。就速度而言,曼托诺的答案使用牛顿法,对于某些情况可能更可取。
这是我的方法...
An alternative approach, which is quite light. Speed-wise, Mantono's answer, that uses the Newton method, might be preferable for certain cases.
Here's my approach...
这是我发现的最好(也是最短)的工作解决方案
http: //faruk.akgul.org/blog/javas-missing-algorithm-biginteger-sqrt/
这是代码:
我已经测试过它并且它工作正常(并且看起来很快)
This is the best (and shortest) working solution I've found
http://faruk.akgul.org/blog/javas-missing-algorithm-biginteger-sqrt/
Here is the code:
I've tested it and it's working correctly (and seems fast)
我正在研究这个问题并成功用Java编写了一个递归平方根查找器。您可以将BDtol更改为您想要的任何内容,但是运行速度相当快,并给出了以下示例:
原始号码1467839114233645767430925372993335637692683931121739087571335401020890062659255388686 50825438150202201473025
SQRT --> 383123885216472214589586756787577295328224028242477055.000000000
然后进行确认
146783911423364576743092537299333563769268393112173908757133540102089006265925538868650825438150202201473025.0000000000 00000000
I was just working on this problem and successfully wrote a recursive square root finder in Java. You can change the BDtol to whatever you want, but this runs fairly quickly and gave me the follow example as a result:
Original number 146783911423364576743092537299333563769268393112173908757133540102089006265925538868650825438150202201473025
SQRT --> 383123885216472214589586756787577295328224028242477055.000000000
Then for confirmation
146783911423364576743092537299333563769268393112173908757133540102089006265925538868650825438150202201473025.000000000000000000
简化了Jim 答案并提高了性能。
Simplified Jim answer and improved performance.
更新(2018 年 7 月 23 日):此技术不适用于较大的值。下面发布了基于二进制搜索的不同技术。
我正在研究因式分解并最终写了这篇文章。
该方法可以如下所示:
希望这有帮助!
Update (23July2018) : This technique does not apper to work for larger values. Have posted a different technique based on binary-search below.
I was looking into factorization and ended up writing this.
The approach can be visualized like this :
Hope this helps!
如果需要性能,
那么对于长度在 64 位到 10240 位之间的数字,使用 Norton Plus 的速度比 Java 内置的 BigInteger Sqrt 快 15 倍到 45 倍。
这是与内置 BigInteger.Sqrt() 的性能比较
更多详细信息
If performance is needed,
then using the Norton Plus is 15X-45X faster than Java's built-in BigInteger Sqrt for numbers between 64 bits and 10240 bits in length.
Here is a performance comparison vs. the built-in BigInteger.Sqrt()
More details here.
我只讨论平方根的整数部分,但您可以修改这个粗略的算法以达到您想要的更高精度:
I am only going as far as the integer part of the square root but you can modify this rough algo to go to as much more precision as you want:
您还可以使用二分查找来查找 x 的平方根
您也可以将其乘以例如 10^10 并通过二分搜索找到像 m 这样的整数,因为 m^2
you can also use binary search to find the square root of x
also you can multiply it to for example 10^10 and find an integer like m by binary search since m^2
这是一个不使用 BigInteger.multiply 或 BigInteger.divide 的解决方案:
Here's a solution that does not use BigInteger.multiply or BigInteger.divide:
我上面发布的答案不适用于大量(但有趣的是!)。因此发布了一种二分搜索方法来确定平方根的正确性。
问候
拉文德拉
The answer I posted above doesn't work for large numbers (but interestingly so!). As such posting a binary-search approach for determining square root for correctness.
Regards
Ravindra
这是一种易于理解的方法,可能没有最佳性能,但它可以在不到一秒的时间内给出单个 BigInteger 的解决方案。
This is an easy to understand way that may not have the best performance but it gives the solution for a single BigInteger in less than a second.
C# 语言的语法与 Java 类似。我写了这个递归解决方案。
像这样调用这段代码(在 Java 中我猜它是“System.out.print”)。
答案是:
27993718524262253829858552106
免责声明:我了解此方法不适用于小于 10 的数字;这是一个 BigInteger 平方根方法。
这很容易解决。将第一种方法更改为以下方法,以便为递归部分提供一些喘息的空间。
The C# language has similar syntax to Java. I wrote this recursive solution.
Call this code like this (in Java I guess it would be "System.out.print").
And the answer is:
27993718524262253829858552106
Disclaimer: I understand this method doesn't work for numbers less than 10; this is a BigInteger square root method.
This is easily remedied. Change the first method to the following to give the recursive portion some room to breathe.
我认为单行就可以完成这项工作。
A single line can do the job I think.