Problem 65
Convergents of e
The square root of 2 can be written as an infinite continued fraction.
The infinite continued fraction can be written, √2 = [1;(2)], (2) indicates that 2 repeats ad infinitum. In a similar way, √23 = [4;(1,3,1,8)].
It turns out that the sequence of partial values of continued fractions for square roots provide the best rational approximations. Let us consider the convergents for √2.
Hence the sequence of the first ten convergents for √2 are:
1, 3/2, 7/5, 17/12, 41/29, 99/70, 239/169, 577/408, 1393/985, 3363/2378, …
What is most surprising is that the important mathematical constant,
e = [2; 1,2,1, 1,4,1, 1,6,1 , … , 1,2k,1, …].
The first ten terms in the sequence of convergents for e are:
2, 3, 8/3, 11/4, 19/7, 87/32, 106/39, 193/71, 1264/465, 1457/536, …
The sum of digits in the numerator of the 10th convergent is 1+4+5+7=17.
Find the sum of digits in the numerator of the 100th convergent of the continued fraction for e.
e的有理逼近
2的算术平方根可以写成无限连分数的形式。
这个无限连分数可以简记为√2 = [1;(2)],其中(2)表示2无限重复。同样的,我们可以记√23 = [4;(1,3,1,8)]。
可以证明,截取算术平方根连分数表示的一部分所组成的序列,给出了一系列最佳有理逼近值。让我们来考虑√2的逼近值:
因此√2的前十个逼近值为:
1, 3/2, 7/5, 17/12, 41/29, 99/70, 239/169, 577/408, 1393/985, 3363/2378, …
最令人惊讶的莫过于重要的数学常数e有如下连分数表示
e = [2; 1,2,1, 1,4,1, 1,6,1 , … , 1,2k,1, …]。
e的前十个逼近值为:
2, 3, 8/3, 11/4, 19/7, 87/32, 106/39, 193/71, 1264/465, 1457/536, …
第10个逼近值的分子各位数字之和为1+4+5+7=17。
求e的第100个逼近值的分子各位数字之和。
package cuppics;
import java.util.Arrays;
import junit.framework.TestCase;
public class Prj65 extends TestCase {
public static final int NUM_OF_CHOOSE = 100;
public void testSquareRootConvergents() {
String str = iterArr(NUM_OF_CHOOSE);
int sum = 0;
for( int i = 0 ; i < str.length(); i ++){
sum += Integer.parseInt( String.valueOf( str.charAt(i)));
}
String fstr = "sum=%d";
fstr = String.format(fstr, sum);
System.out.println(fstr);
}
public int getBits() {
return NUM_OF_CHOOSE * 3 + 1;
}
public int[] power(int[] arr, int multiplier, int b) {
int[] ret = Arrays.copyOf(arr, arr.length);
int count = b;
while (count > 1) {
ret = multiply(ret, multiplier);
count--;
}
return ret;
}
public int[] multiply(int[] arr, int b) {
int[] ret = Arrays.copyOf(arr, arr.length);
for (int i = 0; i < arr.length; i++) {
ret[i] *= b;
}
for (int i = arr.length - 1; i > 0; i--) {
ret[i - 1] = ret[i - 1] + ret[i] / 10;
ret[i] = ret[i] % 10;
}
return ret;
}
public int[] add(int[] a, int[] b) {
assert (a.length == b.length);
int[] ret = new int[a.length];
for (int i = 0; i < a.length; i++) {
ret[i] = a[i] + b[i];
}
for (int i = a.length - 1; i > 0; i--) {
ret[i - 1] = ret[i - 1] + ret[i] / 10;
ret[i] %= 10;
}
return ret;
}
public int[] int2Arr(int val) {
String str = Integer.toString(val, 10);
int[] ret = new int[str.length()];
for (int i = 0; i < ret.length; i++) {
ret[i] = Integer.parseInt(String.valueOf(str.charAt(i)));
}
return ret;
}
public int[] enLarge(int[] val, int bits) {
assert (val.length <= bits);
int[] ret = new int[bits];
for (int i = bits - val.length, j = 0; i < bits; i++, j++) {
ret[i] = val[j];
}
return ret;
}
/**
* [a0;a1,a2....] a0/1, (a1a0 + 1)/a1,
*
* @param n
* @return
*/
public String iterArr(int n) {
int bits = getBits();
// start
int a0 = 2;
int a1 = 1;
//int an = 2;
int p0 = a0;
int p1 = a1 * a0 + 1;
int q0 = 1;
int q1 = a1;
int[] pn_1 = enLarge(int2Arr(p1), bits);
int[] pn_2 = enLarge(int2Arr(p0), bits);
int[] qn_1 = enLarge(int2Arr(q1), bits);
int[] qn_2 = enLarge(int2Arr(q0), bits);
if (n == 1) {
return Integer.toString(a0);
}
assert (n >= 2);
int[] pn = enLarge(int2Arr(0), bits);
int[] qn = enLarge(int2Arr(0), bits);
int k = 1;
for (int i = 3; i <= n; i++) {
if (i % 3 == 0) {
pn = add(multiply(pn_1, 2 * k), pn_2);
qn = add(multiply(qn_1, 2 * (k++)), qn_2);
} else {
pn = add(multiply(pn_1, 1), pn_2);
qn = add(multiply(qn_1, 1), qn_2);
}
pn_2 = Arrays.copyOf(pn_1, bits);
pn_1 = Arrays.copyOf(pn, bits);
qn_2 = Arrays.copyOf(qn_1, bits);
qn_1 = Arrays.copyOf(qn, bits);
}
String str = intArr2Str(pn);
System.out.println(str);
return str;
}
private String intArr2Str(int[] pn) {
StringBuilder sb = new StringBuilder();
int i = 0;
while (pn[i] == 0) {
i++;
}
for (; i < pn.length; i++) {
sb.append(pn[i]);
}
return sb.toString();
}
}