使用Java生成法莱数列
2007-11-28 15:58
381 查看
在上一篇《法莱数列》数列中简要地介绍了法莱数列的特性、如何生成一组法莱数列,以及如何获得指定最大分母的法莱数列的个数。
在这一篇中,我们采用 Java 语言通过其特性来生成法莱数列。由于涉及分数运算,分数类直接就使用 Apache Commons Lang,这个包里有着许多有用的工具类,众多的 Java 开源产品中有许多也引用了这一类库,在这里仅用到 Fraction 类。
为了让各个功能进行模块化管理,设计了三个类:
Farey:用于生成法莱数列的类,其中有获得所有指定数的法莱数列和数列个数的一些方法;
FractionUtil:分数的工具类,这里主要有分数数组的成批输出和按照数学的分式形式进行输出等方法;
FareyTest:用于测试/生成法莱数列。
下面是这三个文件的源代码:
FareyTest.java
import org.apache.commons.lang.math.Fraction;
public class FareyTest {
public static void main(String[] args) {
// 构造一个分母不大于5的法莱数列
Farey farey = new Farey(5);
// 获得法莱数列
Fraction[] fareys = farey.getFaleys();
// 以单行形式输出
FractionUtil.toString(fareys);
// 以数学分式形式输出
FractionUtil.toFractionString(fareys);
}
}
Farey.java
import org.apache.commons.lang.math.Fraction;
public class Farey {
/**
* 法莱数列最大的分母数
*/
private int maxDenominator = 0;
/**
* 法莱数列的个数
*/
private int groups = 0;
/**
* 构造一个分母不大于max的法莱数列
* @param max
*/
public Farey(int max) {
setMax(max);
}
public int getMaxDenominator() {
return this.maxDenominator;
}
public void setMax(int maxDenominator) {
// 法莱数列的最大的分母必须不小于2
if (maxDenominator < 2) {
throw new IllegalArgumentException("数列分母的最大数不能小于2");
}
this.maxDenominator = maxDenominator;
this.groups = 0;
}
/**
* 获得分母不大于max法莱数列的个数
* @return 法莱数列的个数
*/
public int getFareyNumbers() {
if (groups != 0) {
return groups;
}
for (int i = 2; i <= maxDenominator; i++) {
groups++;
for (int j = 2; j < i; j++) {
if (gcd(i, j) == 1) {
groups++;
}
}
}
return groups;
}
/**
* 获得分母不大于max的法莱数列分数数组
* @return 法莱数列分数数组
*/
public Fraction[] getFaleys() {
int groups = getFareyNumbers();
Fraction[] fareys = new Fraction[groups];
fareys[0] = Fraction.getFraction(1, maxDenominator);
if (groups > 1) {
fareys[1] = Fraction.getFraction(1, maxDenominator - 1);
}
for (int i = 2; i < groups; i++) {
fareys[i] = getNextFarey(fareys[i - 2], fareys[i - 1]);
}
return fareys;
}
/**
* 根据法莱数列的前两个分数,获得第三个分数
* @param f1 第一个分数
* @param f2 第二个分数
* @return 法莱数列的第三个分数
*/
private Fraction getNextFarey(Fraction f1, Fraction f2) {
int multiple = (maxDenominator + f1.getDenominator()) / f2.getDenominator();
int numerator = multiple * f2.getNumerator() - f1.getNumerator();
int denominator = multiple * f2.getDenominator() - f1.getDenominator();
return Fraction.getFraction(numerator, denominator).reduce();
}
/**
* 求两个数的最大公约数,经典算法哦
*/
private int gcd(int m, int n) {
if (n == 0) {
return m;
}
return gcd(n, m % n);
}
}
FractionUtil.java
import org.apache.commons.lang.math.Fraction;
public class FractionUtil {
/**
* 以单行形式输出分数数组,以逗号分隔
* @param fracs 分数数组
*/
public static void toString(Fraction[] fracs) {
for (int i = 0, k = fracs.length - 1; i < k; i++) {
System.out.print(fracs[i].toString() + ", ");
}
System.out.println(fracs[fracs.length - 1].toString());
}
/**
* 以普通的分数形式(分子、分数线、分母的上中下式)输出分数数组
* @param fracs 分数数组
*/
public static void toFractionString(Fraction[] fracs) {
char[] line = { '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' };
char[] space = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
int[] width = new int[fracs.length];
int[] numeratorWidth = new int[fracs.length];
int[] denominatorWidth = new int[fracs.length];
for (int i = 0; i < fracs.length; i++) {
numeratorWidth[i] = width(fracs[i].getNumerator());
denominatorWidth[i] = width(fracs[i].getDenominator());
width[i] = Math.max(numeratorWidth[i], denominatorWidth[i]);
}
for (int i = 0; i < fracs.length; i++) {
System.out.print(" "
+ new String(space, 0, width[i] - numeratorWidth[i])
+ fracs[i].getNumerator() + " ");
}
System.out.println();
for (int i = 0; i < fracs.length; i++) {
System.out.print(new String(line, 0, width[i] + 2) + " ");
}
System.out.println();
for (int i = 0; i < fracs.length; i++) {
System.out.print(" "
+ new String(space, 0, width[i] - denominatorWidth[i])
+ fracs[i].getDenominator() + " ");
}
System.out.println();
}
/**
* 获得一个数字的位数
*/
private static int width(int num) {
int width = 0;
while (num != 0) {
num /= 10;
width++;
}
return width;
}
private FractionUtil(){
}
}
在这一篇中,我们采用 Java 语言通过其特性来生成法莱数列。由于涉及分数运算,分数类直接就使用 Apache Commons Lang,这个包里有着许多有用的工具类,众多的 Java 开源产品中有许多也引用了这一类库,在这里仅用到 Fraction 类。
为了让各个功能进行模块化管理,设计了三个类:
Farey:用于生成法莱数列的类,其中有获得所有指定数的法莱数列和数列个数的一些方法;
FractionUtil:分数的工具类,这里主要有分数数组的成批输出和按照数学的分式形式进行输出等方法;
FareyTest:用于测试/生成法莱数列。
下面是这三个文件的源代码:
FareyTest.java
import org.apache.commons.lang.math.Fraction;
public class FareyTest {
public static void main(String[] args) {
// 构造一个分母不大于5的法莱数列
Farey farey = new Farey(5);
// 获得法莱数列
Fraction[] fareys = farey.getFaleys();
// 以单行形式输出
FractionUtil.toString(fareys);
// 以数学分式形式输出
FractionUtil.toFractionString(fareys);
}
}
Farey.java
import org.apache.commons.lang.math.Fraction;
public class Farey {
/**
* 法莱数列最大的分母数
*/
private int maxDenominator = 0;
/**
* 法莱数列的个数
*/
private int groups = 0;
/**
* 构造一个分母不大于max的法莱数列
* @param max
*/
public Farey(int max) {
setMax(max);
}
public int getMaxDenominator() {
return this.maxDenominator;
}
public void setMax(int maxDenominator) {
// 法莱数列的最大的分母必须不小于2
if (maxDenominator < 2) {
throw new IllegalArgumentException("数列分母的最大数不能小于2");
}
this.maxDenominator = maxDenominator;
this.groups = 0;
}
/**
* 获得分母不大于max法莱数列的个数
* @return 法莱数列的个数
*/
public int getFareyNumbers() {
if (groups != 0) {
return groups;
}
for (int i = 2; i <= maxDenominator; i++) {
groups++;
for (int j = 2; j < i; j++) {
if (gcd(i, j) == 1) {
groups++;
}
}
}
return groups;
}
/**
* 获得分母不大于max的法莱数列分数数组
* @return 法莱数列分数数组
*/
public Fraction[] getFaleys() {
int groups = getFareyNumbers();
Fraction[] fareys = new Fraction[groups];
fareys[0] = Fraction.getFraction(1, maxDenominator);
if (groups > 1) {
fareys[1] = Fraction.getFraction(1, maxDenominator - 1);
}
for (int i = 2; i < groups; i++) {
fareys[i] = getNextFarey(fareys[i - 2], fareys[i - 1]);
}
return fareys;
}
/**
* 根据法莱数列的前两个分数,获得第三个分数
* @param f1 第一个分数
* @param f2 第二个分数
* @return 法莱数列的第三个分数
*/
private Fraction getNextFarey(Fraction f1, Fraction f2) {
int multiple = (maxDenominator + f1.getDenominator()) / f2.getDenominator();
int numerator = multiple * f2.getNumerator() - f1.getNumerator();
int denominator = multiple * f2.getDenominator() - f1.getDenominator();
return Fraction.getFraction(numerator, denominator).reduce();
}
/**
* 求两个数的最大公约数,经典算法哦
*/
private int gcd(int m, int n) {
if (n == 0) {
return m;
}
return gcd(n, m % n);
}
}
FractionUtil.java
import org.apache.commons.lang.math.Fraction;
public class FractionUtil {
/**
* 以单行形式输出分数数组,以逗号分隔
* @param fracs 分数数组
*/
public static void toString(Fraction[] fracs) {
for (int i = 0, k = fracs.length - 1; i < k; i++) {
System.out.print(fracs[i].toString() + ", ");
}
System.out.println(fracs[fracs.length - 1].toString());
}
/**
* 以普通的分数形式(分子、分数线、分母的上中下式)输出分数数组
* @param fracs 分数数组
*/
public static void toFractionString(Fraction[] fracs) {
char[] line = { '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' };
char[] space = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
int[] width = new int[fracs.length];
int[] numeratorWidth = new int[fracs.length];
int[] denominatorWidth = new int[fracs.length];
for (int i = 0; i < fracs.length; i++) {
numeratorWidth[i] = width(fracs[i].getNumerator());
denominatorWidth[i] = width(fracs[i].getDenominator());
width[i] = Math.max(numeratorWidth[i], denominatorWidth[i]);
}
for (int i = 0; i < fracs.length; i++) {
System.out.print(" "
+ new String(space, 0, width[i] - numeratorWidth[i])
+ fracs[i].getNumerator() + " ");
}
System.out.println();
for (int i = 0; i < fracs.length; i++) {
System.out.print(new String(line, 0, width[i] + 2) + " ");
}
System.out.println();
for (int i = 0; i < fracs.length; i++) {
System.out.print(" "
+ new String(space, 0, width[i] - denominatorWidth[i])
+ fracs[i].getDenominator() + " ");
}
System.out.println();
}
/**
* 获得一个数字的位数
*/
private static int width(int num) {
int width = 0;
while (num != 0) {
num /= 10;
width++;
}
return width;
}
private FractionUtil(){
}
}
相关文章推荐
- 使用Ant自动化我们的java项目生成
- Java Maven项目使用CXF插件生成WebService代理
- 使用Java为PhoneGap制作的Android软件生成签名
- 在Java中使用weka:手动生成并输出对分类器的评估
- 使用axis2的wsdl2java把wsdl生成java文件
- 【Java】maven工程使用iText生成PDF文件
- 使用Maven的jaxws-maven-plugin插件,将wsdl生成java
- wsdl2java 生成客户端: 具有相同名称 "xxx" 的类/接口已在使用。请使用类定制设置来解决此冲突。
- 使用Java反射(Reflect)、自定义注解(Customer Annotation)生成简单SQL语句
- 在Java中使用dom4j来解析及生成xml文件
- 使用cmd编译java文件成功生成class,但是不能执行
- 使用idea和wsdl生成java代码
- 使用hibernate扩展工具Hbm2JavaTask根据配置文件生成持久化对象类(2.1.2)
- 使用Java生成四位不重复的验证码
- java wsdl反向生成源码,并使用CXF实现客户端调用代码
- 使用Hibernate-tools中的hbm2java和hbm2ddl根据hbm文件自动生成pojo和数据库脚本
- 使用java生成word文档
- 详解Java使用sqlite 数据库如何生成db文件
- java 使用zxing 生成二维码
- 使用exe4j把java程序生成可执行的.exe文件