在本篇博客中,我们将讨论如何使用有效的算法来判断一个大整数是否为平方数。

  给定正整数\(n\),如果存在一个整数\(m\),满足\(m^{2}=n\),那么则称\(n\)为平方数。因此,判断一个大整数\(n\)是否为平方数,很自然的想法就是,从1开始,依次递增,判断这个数的平方是否等于给定的数\(n\),如果是,则\(n\)为平方数,如果这个数的平方大于\(n\),则\(n\)不是平方数。这个想法很简单,但可惜的是,效率却很低,因为我们要遍历\(\sqrt{n}\)个数,当\(n\)很大时,这样的效率是我们不能忍受的。

  那么有没有其他方法呢?这时候,一个公式进入我们的视野,那就是:

\[1+3+5+...+2n-1=n^{2}.
\]

看上去这个公式给了我们一点希望,因为我们不需要从1开始一个一个去找,而是只需要寻找至\(2\sqrt{n}-1\)即可。但我们仔细地分析一下,不难发现,该公式的实质和一个一个找没什么区别,因为我们还是要遍历\(\sqrt{n}\)个数。

  所以,存在有效的算法吗?答案是肯定的!为什么不尝试着去计算\(n\)的平方根呢?按照这个思路,我们具体的算法,结合牛顿法,步骤如下:

  1. 初始值\(x_0=1\), 误差\(\epsilon\)足够小;
  2. 按照\(x_{n+1}=\frac{1}{2}(x_{n}+\frac{n}{x_{n}})\)迭代,直至\(|x_{n}^{2}-n|\leq\epsilon\);
  3. 对\(x_{n}\)取整,结果为\(m\), 如果\(m\)的平方为\(n\),则\(n\)为平方数,否则不是平方数。

  接下来,我们证明这个算法的有效性。首先,我们证明对于\(n\geq1\),都有\(x_{n} > \sqrt{n}\)。我们使用数学归纳法。

  1. 当\(n=1\)时,\(x_{1}=\frac{1}{2}(1+n)>\sqrt{n}\).
  2. 假设\(x_{n}>\sqrt{n}\),则\(x_{n+1}-\sqrt{n}=\frac{x_{n}^{2}+n-2\sqrt{n}x_{n}}{2x_{n}}=\frac{(x_{n}-\sqrt{n})^{2}}{2x_{n}}>0\),所以\(x_{n+1}>\sqrt{n}\).

接着我们再证明\(x_{n}(n\geq1)\)序列递减。因为当\(n>0\)时,有

\[x_{n+1}-x_{n}=\frac{n-x_{n}^{2}}{2x_{n}}<0.
\]

这是因为当\(n\geq1\)时,有\(x_{n}>\sqrt{n}\).

  因此,我们利用第二步的迭代,不停地运算后,所得到的项\(x_{n}\)与\(\sqrt{n}\)很接近,只是稍微大一点。因此,该算法的第三步的判断就是正确的了。

  下面我们将会给出上述算法的Java程序代码,具体如下:

package Problems;

import java.math.BigInteger;
import java.math.BigDecimal; public class IS_Square {
public static void main(String[] args) { // 计算2**128+1
BigInteger F7 = new BigInteger("2").pow(128).add(BigInteger.ONE);
boolean w = is_square(F7);
if(w)
System.out.println(String.format("%s是完全平方数。", F7));
else
System.out.println(String.format("%s不是完全平方数。", F7)); } // 判断是否为完全平方数
public static boolean is_square(BigInteger F7){
// 牛顿法求解平方根, 求解a的平方根
// x为a的平方根,x的初始值为1, 按x = (x+a/x)/2迭代, 误差为error
BigDecimal x = BigDecimal.ONE;
BigDecimal a = new BigDecimal(F7.toString());
BigDecimal eps = new BigDecimal("1");
final BigDecimal error = new BigDecimal("1E-10");
int scale = 100; // 进入循环
while(eps.compareTo(error) == 1){ // eps > error
x = x.add(a.divide(x, scale, BigDecimal.ROUND_HALF_UP)).divide(new BigDecimal("2.0"), scale, BigDecimal.ROUND_HALF_UP);
eps = x.multiply(x).subtract(a).abs();
} BigInteger sqrt = x.toBigInteger(); // 求平方根的整数部分
if(sqrt.pow(2).compareTo(F7) == 0)
return true;
else
return false; } }

其输出结果如下:

340282366920938463463374607431768211457不是完全平方数。

如果将Java程序中的\(F7=2^{128}\),则输出结果为:

340282366920938463463374607431768211456是完全平方数。

  本次分享到此结束,欢迎大家交流~

Java之判断大整数是否为平方数的更多相关文章

  1. 【Java编程】Java中的大整数计算

    在上一篇文章中,我们实现了c语言中的大整数的运算,并且用Miller-Rabin算法实现了对大素数的测试.本来我准备用Java代码实现大整数的运算,查了一下资料发现Java中java.math的Big ...

  2. 手算平方根和基于 Java BigInteger 的大整数平方根的实现

    为了实现任意大数的运算,long用BigInteger替换带哦. 好了废话少数,先说数学原理,也就是手算平方根计算机代码实现!那么什么叫手算平方根了??? 手开方图解 据说前苏联的普通工人都会的(毛熊 ...

  3. JAVA版拆分大整数为2幂的和算法

    import java.util.ArrayList; import java.util.List; public class StrTest { public static void main(St ...

  4. 很火的Java题——判断一个整数是否是奇数

    完成以下代码,判断一个整数是否是奇数: public boolean isOdd(int i) 看过<编程珠玑>的人都知道这道题的答案和其中极为简单的道理. 最普遍的风格,如下: 这个函数 ...

  5. JAVA题目:正整数n若是其平方数的尾部,则称n为同构数 如:5*5=25, 25*25=625 问: 求1~99中的所有同构数

    1 /*题目:正整数n若是其平方数的尾部,则称n为同构数 2 如:5*5=25, 25*25=625 3 问: 求1~99中的所有同构数 4 */ 5 //分析:将1-99分为1-9和10-99,用取 ...

  6. 每日一练之大整数加法(P1255 数楼梯)

    走楼梯走一步还是两步的问题其实就是斐波那契数列(F(n)=F(n-1)+F(n-2),而在int型范围内存在45个相异的数,题干说明楼梯总数可以为5000,则考虑使用字符串进行存储.当两个数相加产生进 ...

  7. Java 实现大整数加减乘除

    自己用Java实现的大整数加减乘除运算.还有可以改进的地方,有兴趣的童鞋可以加以改进.仅供参考,请勿转载! package barrytest; import java.util.ArrayList; ...

  8. ACM学习之路————一个大整数与一个小整数不得不说得的秘密

    这个相对于两个大整数的运算来说,只能说是,low爆了. 只要利用好除法的性质,这类题便迎刃而解.O(∩_∩)O哈哈~ //大整数除一个int数 #include<iostream> #in ...

  9. 【老鸟学算法】大整数乘法——算法思想及java实现

    算法课有这么一节,专门介绍分治法的,上机实验课就是要代码实现大整数乘法.想当年比较混,没做出来,颇感遗憾,今天就把这债还了吧! 大整数乘法,就是乘法的两个乘数比较大,最后结果超过了整型甚至长整型的最大 ...

随机推荐

  1. orm介绍

    昨日回顾: 1 今日内容: 1 orm介绍 1 tools--->Run manage.py Task python3 manage.py makemigrations 只需要敲命令:makem ...

  2. 通过iptables添加QoS标记

    1.什么是QoS QoS是一种控制机制,它提供了针对不同用户或者不同数据流采用相应不同的优先级,或者是根据应用程序的要求,保证数据流的性能达到一定的水准.QoS的保证对于容量有限的网络来说是十分重要的 ...

  3. 关于n维和n-1维欧式空间

    我们从小就说,"点动成线,线动成面,面动成体",其中的空间的概念到底是啥?之前没有好好想过,在机器学习中多次遇到"空间"."超平面",&qu ...

  4. C++ boost.python折腾笔记

    为了让当年研究生时写的图像处理系统重出江湖起到更大的作用,应研究生导师的意见,对原有的c++框架做了python扩展处理,为了避免遗忘,备注如下: 一.boost 编译 下载boost源码,这里使用b ...

  5. Lombok轮子

    前提 自从进公司实习后,项目代码中能用 Lombok 的都用了,毕竟这么好的轮子要充分利用好.也可以减少一些 get/set/toString 方法的编写,虽说 IDEA 的插件可以自动生成 get/ ...

  6. javaWeb中MVC的编程思想示例

    没有学习MVC之前我只写了一个Servlet类(Note_List.java),分层之后,我将这个类分成了5个类(NoteDao.java,,NoteDaoImpl.java,,NoteService ...

  7. 笔记本安装win10之后,无线网有问题

    开机后,连接无线网络,过一段时间,就掉线了,然后再连接也连接不上,必须重启电脑才可以. 解决办法如下: 右键无线网络连接,状态,无线属性,安全,高级设置,勾上为此网络启用联邦信息标准兼容.

  8. Asp.net Identity框架

    Identity提供基于用户和角色的membership管理框架,基本上可以满足业务项目登录操作的所有功能需求. 如果要使用这套框架需要新建User和Role类型分别继承自IUser<TKey& ...

  9. 分布式文件系统 / MQ / 鉴权(轮廓)

    FastDFS的轮廓   /  RabbitMQ的轮廓  /  JWT和RSA非对称加密的轮廓

  10. 机器学习入门07 - 验证 (Validation)

    原文链接:https://developers.google.com/machine-learning/crash-course/validation/ 1- 检查直觉 将一个数据集划分为训练集和测试 ...