[topic] 分数の発見
Posted feedbacks - Java
この場合はあまり役に立ってませんが、分数クラスを定義してみました。 こんな感じでどうでしょうか?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Sample176 {
public static List<Rational> rationalizes(final double d) {
final Map<Rational, Double> map = new HashMap<Rational, Double>();
for (int index = 1; index < 10; index++) {
int nume = (int) (d * index);
Rational r1 = new Rational(nume, index);
Rational r2 = new Rational(nume + 1, index);
if ((r2.doubleValue() - d) - (d - r1.doubleValue()) > 0) {
map.put(r1, Math.abs(r1.doubleValue() - d));
} else {
map.put(r2, Math.abs(r2.doubleValue() - d));
}
}
List<Rational> result = new ArrayList<Rational>(map.keySet());
Collections.sort(result, new Comparator<Rational>() {
public int compare(Rational o1, Rational o2) {
return Double.compare(map.get(o1), map.get(o2));
}
});
return result;
}
public static void main(String[] args) {
System.out.println(rationalizes(1.732051));
System.out.println(rationalizes(3.141593));
System.out.println(rationalizes((double) 1920 / 1080));
}
}
class Rational extends Number {
public final int numerator;
public final int denominator;
public Rational(int p, int q) {
int nume = p;
int deno = q;
if (deno == 0) {
throw new IllegalArgumentException("#N/A");
} else if (nume == 0) {
deno = 1;
} else if (deno < 0) {
nume *= -1;
deno *= -1;
}
int r = gcd(nume, deno);
numerator = nume / r;
denominator = deno / r;
}
private int gcd(int n, int m) {
int p = n;
int q = m;
int r = p % q;
while (r > 0) {
p = q;
q = r;
r = p % q;
}
return q;
}
@Override
public int intValue() {
return numerator / denominator;
}
@Override
public long longValue() {
return this.intValue();
}
@Override
public float floatValue() {
return (float) this.doubleValue();
}
@Override
public double doubleValue() {
return (double) numerator / denominator;
}
@Override
public int hashCode() {
return numerator + denominator * 7;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Rational)) return false;
Rational other = (Rational) obj;
return this.denominator == other.denominator
&& this.numerator == other.numerator;
}
@Override
public String toString() {
return String.format("%d/%d", numerator, denominator);
}
}
|



gandalf #6278() Rating1/1=1.00
schemeにはrationalizeという手続きがありますが、これは結果を一つしか返しません。そして、複数の結果が欲しい場合も稀にあります。
そこで、非負の実数aが一つ与えられたときに、以下の条件を満たす分数b/cをaに近い順に全て表示する手続きを考えてみてください。条件は、 1. 分数b/cよりaに近い分数d/cは存在しない 2. 分数b/cは既約 3. cは1桁の整数 です。
例をいくつかあげます(あってると思うけど...)。
a = 1.732051 12/7 7/4 16/9 5/3 9/5 3/2 2/1
a = 3.141593 22/7 25/8 19/6 28/9 16/5 13/4 3/1
a = 1920 / 1080 16/9 9/5 7/4 11/6 12/7 5/3 2/1
[ reply ]