.NET 4.0为任意大整数提供了System.Numerics.BigInteger
类型。我需要计算BigInteger
的平方根(或合理的近似值 - 例如整数平方根)。所以我不必重新实现轮子,有没有人有一个很好的扩展方法呢?计算BigInteger的平方根(System.Numerics.BigInteger)
回答
我不知道,如果牛顿的方法是计算BIGNUM平方根的最好方式,因为它涉及到这对大数慢区划。您可以使用CORDIC方法,只使用加法和移位(这里显示为无符号整型)
static uint isqrt(uint x)
{
int b=15; // this is the next bit we try
uint r=0; // r will contain the result
uint r2=0; // here we maintain r squared
while(b>=0)
{
uint sr2=r2;
uint sr=r;
// compute (r+(1<<b))**2, we have r**2 already.
r2+=(uint)((r<<(1+b))+(1<<(b+b)));
r+=(uint)(1<<b);
if (r2>x)
{
r=sr;
r2=sr2;
}
b--;
}
return r;
}
有只使用加法和移位,称为“Dijkstras平方根”类似的方法,例如在这里解释说:
这个计算整数的整数平方根。如果你需要小数,你可以预先缩放操作数。 – 2010-08-08 00:31:11
通过继续b的负值循环并将-n的左移转换为n的右移,可以计算出任意精度。 – 2010-08-08 19:28:43
轻松适应64位长,这正是我所需要的。谢谢! – yoyo 2013-09-04 20:49:41
Check if BigInteger is not a perfect square有代码来计算一个Java BigInteger的整数平方根。在这里它被翻译成C#,作为扩展方法。
public static BigInteger Sqrt(this BigInteger n)
{
if (n == 0) return 0;
if (n > 0)
{
int bitLength = Convert.ToInt32(Math.Ceiling(BigInteger.Log(n, 2)));
BigInteger root = BigInteger.One << (bitLength/2);
while (!isSqrt(n, root))
{
root += n/root;
root /= 2;
}
return root;
}
throw new ArithmeticException("NaN");
}
private static Boolean isSqrt(BigInteger n, BigInteger root)
{
BigInteger lowerBound = root*root;
BigInteger upperBound = (root + 1)*(root + 1);
return (n >= lowerBound && n < upperBound);
}
非正式测试表明这比Math.Sqrt慢约75倍,对于小整数。 VS分析器指向isSqrt中的乘法作为热点。
BigInteger不会优化除法运算符。 Bitshift正确的一个,而不是二分之一将改善性能(至少在我的情况下)。 – GeirGrusom 2011-10-28 06:59:31
UpperBound定义也可以被重写为多项式展开式'BigInteger upperBound = lowerBound + root + root + 1'或在返回中内联为'return n> = lowerBound && n <= lowerBound + root + root' – 2014-08-13 22:57:27
简短的回答:(但要注意,看到下面有详细介绍)
Math.Pow(Math.E, BigInteger.Log(pd)/2)
凡pd
表示要在其上执行平方根运算的BigInteger
。
长一点的回答和解释:
另一种方式来理解这个问题是理解平方根和日志如何工作。
如果你有等式5^x = 25
,要解决x
我们必须使用日志。在这个例子中,我将使用自然日志(其他基地的日志也是可能的,但自然日志是简单的方法)。
5^x = 25
重写,我们有:
x(ln 5) = ln 25
为了分离X,我们有
x = ln 25/ln 5
我们认为,这将导致x = 2
。但因为我们已经知道x(x = 2,在5^2),所以让我们改变我们不知道的东西,并写出一个新的方程,并解决新的未知问题。设x是平方根运算的结果。这给了我们
2 = ln 25/ln x
重写分离X,我们有
ln x = (ln 25)/2
要删除日志,我们现在使用的自然对数的特殊身份和特殊号码ê。具体来说,e^ln x = x
。重写等式现在让我们
e^ln x = e^((ln 25)/2)
简化左手边,我们有
x = e^((ln 25)/2)
其中x将是25的平方根您还可以扩展这个想法告诉任何根或号码,并且x的第y根的通式变成e^((ln x)/y)
。
现在要专门将这个应用于C#,BigIntegers和这个问题,我们只需实现公式。 警告:虽然数学是正确的,但有限制。这种方法只会让你在附近,有一个很大的未知范围(取决于你操作的数字有多大)。也许这就是微软没有实施这种方法的原因。
// A sample generated public key modulus
var pd = BigInteger.Parse("101017638707436133903821306341466727228541580658758890103412581005475252078199915929932968020619524277851873319243238741901729414629681623307196829081607677830881341203504364437688722228526603134919021724454060938836833023076773093013126674662502999661052433082827512395099052335602854935571690613335742455727");
var sqrt = Math.Pow(Math.E, BigInteger.Log(pd)/2);
Console.WriteLine(sqrt);
注:的BigInteger.Log()
方法返回一个double,所以两个问题出现。 1)数字不精确,并且2)Log()
可以为BigInteger
输入处理什么上限。要检查上限,我们可以查看自然日志的正常形式,即ln x = y
。换句话说,e^y = x
。由于double
是BigInteger.Log()
的返回类型,因此最大的BigInteger
将会是e增加到double.MaxValue
。在我的电脑上,那将是e^1.79769313486232E+308
。不精确性未被处理。任何人想要执行BigDecimal
并更新BigInteger.Log()
?
消费者当心,但它会让你在附近,并且平方结果的确会产生一个类似于原始输入的数字,达到如此多的数字,而不是像RedGreenCode的答案那样精确。快乐(方形)生根! ;)
您可以将其转换为您选择的语言和变量类型。这里是JavaScript中截断的squareroot(对我来说是最新鲜的),它利用了1 + 3 + 5 ... +第n个奇数= n^2。所有的变量都是整数,只是加减。
var truncSqrt=function(n){
var oddNumber=1;
var result=0;
while (n>=oddNumber) {
n-=oddNumber;
oddNumber+=2;
result++; }
return result; }`
真的很好奇这相对于其他方法执行。 – 2016-09-22 05:38:12
- 1. 计算2的平方根
- 2. Java平方根计算器?
- 3. BigInteger和BigDecimal的平方根和++运算符
- 4. SQL中的NormDist和平方根计算
- 5. 递归算法来计算平方根,立方根
- 6. biginteger计算问题
- 7. 安卓平方根计算错误
- 8. 平方根计算图灵机
- 9. 如何在python中计算平方根?
- 10. 计算浮动平方根在python
- 11. 平分法平方根计算的问题
- 12. 平方和计算
- 13. 计算一个数字的平方根的程序。
- 14. 当计算平方根的分数时奇怪的输出
- 15. 如何计算Go中的大整数的平方根?
- 16. Java的计算器平方根不上的NetBeans 8.2上运行
- 17. 计算两个定点分数的平方根的解释
- 18. C/C++实现的BigInteger计算阶乘
- 19. 为什么DLIB计算LBP一致描述符的平方根?
- 20. 计算用户输入编号的平方根
- 21. DC.js计算平均根据尺寸
- 22. 使用GPU加速BigInteger计算
- 23. Java使用GPU与BigInteger进行计算
- 24. 巴比伦平方根算法 - 初始估计值
- 25. 二进制搜索来计算平方根(Java)
- 26. 逆平方根:在数学库或如何计算它
- 27. 在Scala中递归地计算平方根
- 28. Protobuff连载System.Numerics.BigInteger
- 29. 如何计算数字的平方?
- 30. 计算二次方程的根。 C++
对不起,但我的脑子因为刚开始考虑这个背后的数学而感到痛苦:-P。而且nubers很大才能投入很长时间? – Alxandr 2010-08-07 23:17:39
是的,我需要大约256位,可能是512 - 所以没有作弊使用 – Anonym 2010-08-08 01:01:56