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

  给定正整数\(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. django 图书管理系统

    一.图书管理系统 单表的增删改查 1.创建项目 2.注释掉中间件 就可以提交post 请求 3.配置静态文件 并手动创建static 文件夹存放静态文件  二.具体的数据库配置 1.创建数据库  2. ...

  2. access纯jdbc连接

    Class.forName("com.hxtt.sql.access.AccessDriver"); String url = "jdbc:Access:///c:/a/ ...

  3. Asp.net Identity框架

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

  4. 在windows上安装wamp时遇到apache无法启动,图标为橙色

    1.首先测试端口号是否被占用,如果端口号被占用,修改相对应文件的端口号,修改端口号的方法网上很容易搜到. 2.如果端口号没有被占用,cd到httpd.exe目录下,查看错误原因,这里我显示的错误是ht ...

  5. [转]Linux操作系统tcpdump抓包分析详解

    PS:tcpdump是一个用于截取网络分组,并输出分组内容的工具,简单说就是数据包抓包工具.tcpdump凭借强大的功能和灵活的截取策略,使其成为Linux系统下用于网络分析和问题排查的首选工具. t ...

  6. JavaScript(变量、作用域和内存问题)

    JavaScript是一个变量松散型的语言.(不像Java一样强类型语言.) JavaScript变量包括两种:基本类型(简单的数据段)和引用类型(对象). 一.基本数据类型(5种) Undefine ...

  7. UnityTips:使用反射调用内部方法拓展编辑器

    大家都知道Unity是一个C/C++的游戏引擎,C#只是Unity提供的脚本层.因此大部分功能都是通过C#来调用底层的C++代码的.而一些朋友可能不知道的是,其实Unity的C#代码中也有很多方法是我 ...

  8. MyBatis 源码分析系列文章合集

    1.简介 我从七月份开始阅读MyBatis源码,并在随后的40天内陆续更新了7篇文章.起初,我只是打算通过博客的形式进行分享.但在写作的过程中,发现要分析的代码太多,以至于文章篇幅特别大.在这7篇文章 ...

  9. 我的书单(Book List)

    code[class*="language-"], pre[class*="language-"] { background-color: #fdfdfd; - ...

  10. 二、activiti工作流-创建25张表

    首先我们在eclipse上创建一个maven项目 然后在resources下面创建一个file,并命名问activiti.cfg.xml activiti.cfg.xml的配置内容如下 <?xm ...