Tá aí.
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Locale;
public class Serie
{
private static final int MAX_DOUBLE = 308;
private static final double T[] = new double[MAX_DOUBLE];
private static final int MAX_BD = 5000;
private static final BigDecimal T_BD[] = new BigDecimal[MAX_BD];
private static final BigDecimal TEN_BD = BigDecimal.valueOf(10);
//private static final BigDecimal ZERO_BD = BigDecimal.valueOf(0); Excluida
/*[01]-----------------------------------------------------------
* Funcao de aproximacao de Gorducho
-----------------------------------------------------------------*/
public static double gordsApproach(int n, int k)
{
return 1 - Math.exp(-(n/Math.pow(10,k)));
}//fim de gordsApproach()
/*[02]-----------------------------------------------------------
* Retorna o erro relativo
-----------------------------------------------------------------*/
public static String relativeErr(String result, double estimate)
{
double bdResult = new BigDecimal(result).doubleValue();
double err = Math.abs(bdResult - estimate)/bdResult * 100;
return String.format(Locale.US,"Erro de aproximacao = %8.4f %%",err);
}//fim de relativeErr()
/*[03]-----------------------------------------------------------
* Retorna uma String com o mesmo char repetido howManyTimes
-----------------------------------------------------------------*/
public static String repeat(char c, int howManyTimes)
{
char[] array = new char[howManyTimes];
Arrays.fill(array,c);
return new String(array);
}//fim de repeat()
/*[04]-----------------------------------------------------------
* Retorna 10 elevado a power em BigDecimal
-----------------------------------------------------------------*/
public static BigDecimal exp10(int power)
{
return new BigDecimal("1" + repeat('0',power));
}//fim de exp10()
/*[05]-----------------------------------------------------------
* Retorna p(n,k) em BigDecimal
-----------------------------------------------------------------*/
public static BigDecimal p3(int n, int k)
{
int dif = n - k;
BigDecimal s =
new BigDecimal(Integer.toString(dif + 1)).multiply(exp10(dif));
BigDecimal pow = new BigDecimal("1");
for (int recursiveN = dif; k <= recursiveN; recursiveN--)
{
//if (T_BD[recursiveN].compareTo(ZERO_BD) == 0) Excluida
if (T_BD[recursiveN] == null)
T_BD[recursiveN] = (p3(recursiveN,k));
s = s.subtract(T_BD[recursiveN].multiply(pow));
pow = pow.multiply(TEN_BD);
}
return s;
}//fim de p3()
/*[06]-----------------------------------------------------------
* Retorna p(n,k) em double
-----------------------------------------------------------------*/
public static double p2(int n, int k)
{
int dif = n-k;
double s = Math.pow(10,dif) * (dif+1);
double pow = 1;
for (int recursiveN = dif; k <= recursiveN; recursiveN--)
{
if (T[recursiveN] == 0) T[recursiveN] = p2(recursiveN,k);
s -= T[recursiveN] * pow;
pow *= 10;
}
return s;
}//fim de p2()
/*[07]-----------------------------------------------------------
* Primeira versao de p(n,k)
-----------------------------------------------------------------*/
public static double p(int n, int k)
{
if (n<k)
return 0;
else
{
double s = Math.pow(10,n-k) * (n-k+1);
for (int i = 0; i <= (n-k); i++)
s = s - p(n-k-i,k) * Math.pow(10,i);
return s;
}
}//fim de p()
/*[08]-----------------------------------------------------------
* Programa principal
-----------------------------------------------------------------*/
public static void main(String[] args)
{
int k = 3;
//for (int i = k; i <= MAX_DOUBLE; i++)
//System.out.println("P("+i+") = " + p2(i,k)/Math.pow(10,i));
/*
Inicializa com zeros (em BigDecimal) o array T_BD[]
*/
//for (int i = 0; i <= MAX_BD - 1; i++) T_BD = ZERO_BD; Excluida!
/*
Lista resultados em BigDecimal de k a MAX_BD
*/
for (int i = k; i <= MAX_BD; i++)
{
String bdResult = p3(i,k).toString();
int lgth = bdResult.length();
/*
Retira os zeros a direita no resultado
*/
for (int j = lgth - 1; j >= 0; j--)
if (bdResult.charAt(j) != '0')
{
bdResult = bdResult.substring(0,j+1);
break;
}
/*
"Divide" p3(i,k) por 10 elevado a i
*/
String result = "0." + repeat('0', i - lgth) + bdResult;
/*
Formata a String de saida
*/
String s = relativeErr(result, gordsApproach(i,k)) +
String.format("%14s",String.format(" P(%d,%d) = ",i,k)) +
result;
System.out.println(s);
}//fim do for i
System.exit(0);//Aborta programa antes de executar o loop de simulacao
/*
Obtem por simulacao os mesmos resultados calculados pela
funcao p(n,k)
*/
double limit = 999;
for (int a = 3; a <= 9; a++)
{
int count = 0;
for (int b = 0; b <= limit; b++)
if (String.valueOf(b).contains("123")) count++;
System.out.println(limit+" "+count+" P("+a+") = "+(double)count/(limit + 1));
limit = limit * 10 + 9;
}
}//fim de main()
}//fim da classe Serie
*Fonte monoespaçada
**Fiz pequenas alterações para retirar uma complicaçãozinha desnecessária. As linhas excluídas estão em vermelho, como comentários. A linha incluída está em verde.