Java语言求解完美数代码分析
作者:ljtyzhr 发布时间:2023-01-28 10:17:58
1、概念
首先我们理解一下,什么叫做完美数?
问题描述:若一个自然数,它所有的真因子(即除了自身以外的约数)的和恰好等于它本身,这种数叫做完全数。简称“完数”
例如,
6=1+2+3
28=1+2+4+7+14
496=1+2+4+8+16+31+62+124+248
8128=1+2+4+8+16+32+64+127+254+508+1016+2032+4064
按照完数的定义,其实用程序求解完数并不是太难,先求解出这个数的所有真因子,然后相加,判断是否等于它本身即可。但是,在这个数很小的时候,没有什么问题,一旦这个数字超过一定的数值,那么问题就来了,程序的执行效率就会变得低下。
我们优化程序的算法逻辑,往往会考虑一个问题,怎么高效的利用计算机的特性?在它所定义的算法中,有没有大量重复的无用功呢?沿着这样的思路去考虑这个问题,我们会很快得到另外的一种解决方案。
2、说明
2.1分析
在这里,我们会不会很容易就想到,之前我们提到过的分解因式?是的,在解决完美数的时候,我们会用到分解因式。一般来说,求解完美数会经过三个步骤:
1.求出一定数目的质数表
2.利用质数表求指定数的因式分解
3.利用因式分解求所有真因数和,并检查是否为完美数
2.2难点
初看之下,第一步和第二步是没什么问题的,我们在前面的两篇文章中已经探讨过了,不清楚的同学可以查看。
重点是在第三步,如何求真因数和?方法很简单,要先知道将所有真因数(有不清楚真因数概念的同学,去看看)和加上该数本身,会等于该数的两倍(有些同学不知道,现在应该也知道了吧?),例如:
2 * 28 = 1 + 2 + 4 + 7 + 14 + 28
事实上,这段等式可以转换为:(代码输入错误,我用截图好了)
发现没有?2和7都是因式分解得到的,那么,程序是不是有了简化的地方?
2.3结论
只要求出因式分解,就可以利用循环求得等式后面的值,将该值除以2就是真因数和了;等式后面第一眼看时可能想到使用等比级数公式来解,不过会使用到次方运算,可以在进行读取因式分解阵列时,同时计算出等式后面的值。
3、代码
import java.util.ArrayList;
// 求解完美数
public class PerfectNumber {
// 传入一个值,求解至少多少个完美数
public static int[] lessThan(int number) {
int[] primes = Prime.findPrimes(number);
ArrayList list = new ArrayList();
for(int i = 1; i <= number; i++) {
int[] factors = factor(primes, i);
if(i == fsum(factors))
list.add(new Integer(i));
}
int[] p = new int[list.size()];
Object[] objs = list.toArray();
for(int i = 0; i < p.length; i++) {
p[i] = ((Integer) objs[i]).intValue();
}
return p;
}
// 分解因式
private static int[] factor(int[] primes, int number) {
int[] frecord = new int[number];
int k = 0;
for(int i = 0; Math.pow(primes[i], 2) <= number;) {
if(number % primes[i] == 0) {
frecord[k] = primes[i];
k++;
number /= primes[i];
}
else
i++;
}
frecord[k] = number;
return frecord;
}
// 因式求和
private static int fsum(int[] farr) {
int i, r, s, q;
i = 0;
r = 1;
s = 1;
q = 1;
while(i < farr.length) {
do {
r *= farr[i];
q += r;
i++;
} while(i < farr.length - 1 &&
farr[i-1] == farr[i]);
s *= q;
r = 1;
q = 1;
}
return s / 2;
}
public static void main(String[] args) {
int[] pn = PerfectNumber.lessThan(1000);
for(int i = 0; i < pn.length; i++) {
System.out.print(pn[i] + " ");
}
System.out.println();
}
}
来源:http://blog.csdn.net/ljtyzhr/article/details/38962569


猜你喜欢
- 本文实例讲述了java之swing下拉菜单实现方法。分享给大家供大家参考。具体如下:import java.awt.*;import jav
- 构造函数public class FileDemo { public static void
- java -jar设置添加启动参数方法java -jar 参数前后位置说明springboot项目启动的时候可以直接使用java -jar
- EditText和TextView一样,也可以进行图文混排。所不同的是,TextView只用于显示图文混排效果,而EditText不仅可显示
- 程序员日常工作中,发送http请求特别常见。本文以Java为例,总结发送http请求的多种方式。1. HttpURLConnection使用
- 目录前言一 安全性问题1.1 调用接口的先决条件-token1.2 使用POST作为接口请求方式1.3 客户端IP白名单1.4 单个接口针对
- 初次接触spring-boot的时候,我们经常会看到这样的文章:“
- 树的同构备忘!定义:给定两棵树r1、r2,如果r1可以通过若干次的左子树和右子树互换,使之与r2完全相同,这说明两者同构。举例树的构造树可以
- isInstance和isAssignableFromobj instanceof Class判断obj是不是Class或者Class的子类
- 修改整理的一个通用类,用来操作oracle数据库 十分的方便,支持直接操作sql语句和Hash表操作.现在修补MIS我都用这个类,节约了大
- 配置文件中使用${}注入值方式在springboot中使用System.setProperty设置参数user: user-na
- 文件格式分别如下 package txtobject ReadTxt {def readFromTxtBy
- spring @Autowired注解无法注入问题简述在使用spring框架的过程中,常会遇到这种两情况:1、在扫描的包以外使用需要使用ma
- 综述在Retrofit2.0使用详解这篇文章中详细介绍了retrofit的用法。并且在retrofit中我们可以通过ResponseBody
- 本文实例为大家解析了Zxing生成二维码的经典案例,供大家参考,具体内容如下1、首先呢,先编译 compile ‘com.google.zx
- 采取的方法是Fragment+FragmentTabHost组件来实现这种常见的app主页面的效果首先给出main.xml文件
- 在说明映射文件规则之前,先来回顾一下ORM相关概念。1.ORM概念ORM(Object Relationship Mapping)对象关系映
- 今天传图片,用的base64字符串,POST方法,前端传送的时候总是莫名其妙的崩溃,去网上搜了半天,以为是文件大小被限制了,但是我这个是字符
- XML作为一种业界公认的数据交换格式,在各个平台与语言之上,都有广泛使用和实现。其标准型,可靠性,安全性......毋庸置疑。在androi
- 本次教程将教大家如何用monkeyrunner进行android的自动化测试,包括环境的搭建、monkeyrunner和uiautomato