java biginteger sqrt_浅谈 BigInteger.Sqrt 方法

我们知道 .NET Framework 4 中已经有了 System.Numerics.BigInteger 结构。但是该 BigInteger 结构中没有 Sqrt 方法。那么就让我们自己来写一个吧:01:usingSystem;

02:usingSystem.Numerics;

03:

04:namespaceSkyiv

05:{

06: public static classExtensions

07:{

08: public staticBigIntegerSqrt(thisBigIntegerx)

09: {

10: if(x.Sign < 0) throw newArgumentOutOfRangeException("x", "must be greater than or equal to zero");

11: BigIntegerlow, high;

12: GetLowAndHigh(x, outlow, outhigh);

13: varmid = low;

14: varcmp = 0;

15: while(low.CompareTo(high) <= 0)

16: {

17: mid = (low + high) / 2;

18: cmp = (mid * mid).CompareTo(x);

19: if(cmp < 0) low = mid + 1;

20: else if(cmp > 0) high = mid + (-1);

21: else returnmid;

22: }

23: if(cmp > 0) mid--;

24: returnmid;

25: }

26:

27: static voidGetLowAndHigh(BigIntegerx, outBigIntegerlow, outBigIntegerhigh)

28: {

29: varn = x.ToByteArray().Length;

30: if(n < 2)

31: {

32: low = 0;

33: high = x;

34: return;

35: }

36: varbs = new byte[n / 2 + 1];

37: vark = bs.Length - 2;

38: if(n % 2 == 0)

39: {

40: bs[k] = 0x0B;

41: low = newBigInteger(bs);

42: bs[k] = 0xB6;

43: high = newBigInteger(bs);

44: }

45: else

46:{

47: bs[k] = 0xB5;

48: low = newBigInteger(bs);

49: bs[k] = 0x51;

50: bs[k + 1] = 0x0B;

51: high = newBigInteger(bs);

52: }

53: }

54: }

55:}

上述程序中第 27 到 53 行的 GetLowAndHigh 方法用于获得指定的大整数的平方根的下限和上限,然后在第 8 到 25 行的 Sqrt 方法中使用二分搜索来找出所求的平方根。

BigInteger.ToByteArray 方法将 BigInteger 转换为字节数组。对于大于零的 BigInteger ,转换后的字节数组的长度固定的情况下,最小值为 00-80-00-00-00 形式,最大值为 7F-FF-FF-FF-FF 形式,刚好比下一组最小值小一。如下表所示:

n

x

Sqrt(x)

2

00-80

0B

3

00-80-00

00-B5

4

00-80-00-00

0B-50

5

00-80-00-00-00

00-B5-04

6

00-80-00-00-00-00

0B-50-4F

7

00-80-00-00-00-00-00

00-B5-04-F3

8

00-80-00-00-00-00-00-00

0B-50-4F-33

9

00-80-00-00-00-00-00-00-00

00-B5-04-F3-33

从上表中可以看到,假设 x 转换为字节数组后,长度为 n ,则 Sqrt(x) 转换为字节数组后,其长度为 n / 2 + 1。

对于 n 为偶数的情况(程序中第 40 到 43 行):

最小值大于 00-0B-00-00-...

最大值小于 00-B6-00-00-...

对于 n 为奇数的情况(程序中第 47 到 51 行):

最小值大于 00-B5-00-00-...

最大值小于 0B-51-00-00-...

在 .NET Framework 2.0 中并没有 BigInteger。我以前自己用 C# 写过 BigInteger,也实现了 Sqrt 方法。可以参见以下随笔:

使用快速傅里叶变换实现 BigInteger 时,是调用 BigArithmetic 类的静态方法。其中 Sqrt 方法是使用牛顿迭代法计算平方根:

Ui+1 = Ui (3 - VUi2) / 2

则 U∞二次收敛于 1/√V,最后乘以 V 就得到√V。求平方根的速度比本文中的二分搜索法要快。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值