viernes, 15 de marzo de 2013

Números primos y conjetura de Goldbach.




Pequeña y poco útil herramienta, ¿ alguien se ha encontrado en el  mundo real con la necesidad de saber si un número es primo o no?  ,para saber si un número es primo o no y para saber cuales son los dos números primos que sumados dan un número par determinado.
Funciones utilizadas:
  1. Coincidir()
  2. Indice()
  3. Si()
  4. Entero
Rangos o variables con nombre:
  1. CGB=ConjeturaGoldbach!$B$1
  2. Num=Primo!$B$1
  3. Primos=NPrimos!$A:$A
  4. RaizNum=ENTERO(RAIZ(Primo!$B$1))
  5. RanSum=INDIRECTO("$g$3:$g" & Primo!$D$1+1)
  6. UCoin=Primo!$D$1

¿ Como podemos calcular si un número es primo o no? En principio un número primo es aquel que solo es divisible por uno o por si mismo. Si un número no es primo tiene al menos dos divisores, uno con un valor inferior a su raíz cuadrada  y el otro con un valor superior a esa raíz, salvo en el caso de que su raíz cuadrada sea un valor entero, en el solo podemos asegurar un divisor. Además al menos uno de los divisores es un número primo. Por tanto, para calcular si un número es primo, o no, se puede dividir por todos y cada uno de los números comprendidos entre el entero de su raíz cuadrada y dos. Si una de esas divisiones nos da entero, en número no es primo y si en ninguna de ellas nos da entero el número es primo. Este es el camino largo, para acortar el proceso basta con dividir por los números primos que hay entre su raíz cuadrada y dos. Es mas complejo pero permite, dadas las limitaciones del Excel, aumentar el máximo numero a comprobar. En la hoja de cálculo utilizo este segundo método. Los 65536 primeros números primos los encuentro mediante programación, con la siguiente subrutina:

Sub NumPrimos()
Dim N, I, X As Double, Es
N = 2
I = 1
Sheets(1).UsedRange.Clear

While N < 65536

I = I + 2
X = Int(Sqr(I))
Es = True
For j = X To 2 Step -1
If I / j = Int(I / j) Then
Es = False
Exit For
End If
Next
If Es Then
N = N + 1
Sheets(1).Range("a" & N).Value = I
End If

Wend

End Sub

La hoja NPrimos contiene los 65536 primeros números primos, en la hoja "Primo" hago encuentro si un numero es primo o no. En la hoja "ConjeturaGoldbach" encuentro al menos una pareja de números primos que sumados dan un determinado número par.  El mecanismo de funcionamiento exige, en ambas hojas, activar el filtro después de escribir el número, eligiendo 1 en el desplegable de valores de la columna G en Primo y de la columna I en la conjetura.

Números primos. Hoja "PRIMO":

  1. El numero a procesar se escribe en B1 (variable con nombre Num)
  2. Incluyo en la columna C, a partir de la línea 3, los números enteros del 0 al  655333.
  3. En D1, mediante la fórmula =COINCIDIR(RaizNum;Primos;1) (ver rangos y variables con nombre) , localizo el mayor número primo que es menor o igual al entero  de la raíz cuadrada del número.
  4. En la columna E divido el número Num por los números primos menores al primero encontrado. Para ello utilizo la función  =Num/INDICE(Primos;UCoin-$C3). Esta función produce un error cuando UCoin-$C3 es menor que uno.
  5. En la columna G, mediante la función condicional =SI(ENTERO($E3)=E3;1;0) indico que si el resultado de la división del apartado anterior es entero de un uno y si no un cero.
  6. Sumo la columna G en la variable con nombre RanSum ,=INDIRECTO("$g$3:$g" & Primo!$D$1+1). Si un número no es primo tiene varios divisores primos, hasta llegar a uno, y si lo es solo tiene uno, el uno. En ambos casos hay que sumar hasta la línea del uno, pero no incluirla. Esto significa que si el último primos menor o igual a la raíz está en la línea N hay que sumar N-1 terminos. Como empezamos el la línea tres, corregimos la fórmula hasta D1+1. No es necesario gestionar los errores dado que solo utilizamos el rango en el que no se ha producido ninguno.
  7. En H, mediante la función condicional =SI(SUMA(RanSum)=0;"Es primo";"No es primo") presento el resultado del proceso. 
  8. Lamentablemente el filtro no se actualiza automáticamente, hay que activarlo cada vez, seleccionando uno en G.

Hoja ConjeturaGoldbach:

  1. El número par a comprobar se sitúa en B1. 
  2. Cálculo la mitad de ese número en d1.
  3. Encuentro el mayor número primo que es menor o igual a la mitad del número procesado.
  4. El algoritmo consiste en restar cada número primo inferior a igual a la mitad del número procesado, restarlo del número para después encontrar, media la función COINCIDIR, el último primo menor que el resultado de la resta. Si este segundo número primo encontrado sumado al primero suman igual que el número procesado la conjetura se cumple. En la columna I, mediante el condicional SI se prepara, mediante 0 o 1 la selección del par de primos que hacen que la conjetura se cumpla.
  5. Lamentablemente el filtro no se actualiza automáticamente, hay que activarlo cada vez, seleccionando uno en I.









jueves, 7 de marzo de 2013

Conversión de ficheros formato Kml a formato PLT


Y a formato GPX. Un fichero KML es uno de los tipos de fichero que utiliza  Google Hearth para representar una ruta. Es un fichero de texto leíble con cualquier editor de textos.
Una ruta en formato KML esta formada por una serie de comandos XML. Cada comando está dedicado a un tema, cabecera, nombre, el color, etc... Aquí solo nos interesan las coordenadas, que son una única línea en la que están todos los puntos de una ruta separados por un espacio. Cada punto, a su vez, está formado por un valor X para la longitud, un valor Y para la latitud y un valor Z para la altura, separados por comas X,Y,Z 
Esta estructura de datos nos crea un problema a la hora de trabajar con ellos en Excel, los datos no vienen en columnas, vienen en una sola línea, lo que junto a que una hoja excel tiene 256 columnas como máximo y a que el número de caracteres en una celda también es limitado nos impide trabajar, al menos, con rutas de mas de 256 puntos.
Cuando empecé este trabajo no tuve en cuenta estas limitaciones, me limité a abrir el fichero KML con excel y a procesar la línea con los puntos de la ruta. En esta primera forma de trabajar , durante el primer paso, necesitaba una columna por punto. Esta la limitación de 256 columnas me impedía trabajar rutas de mas 256 puntos. Posteriormente pensé ¿Como convierto esa línea de n puntos en una columna con n líneas de un punto? Se puede hacer y de hecho es relativamente sencillo. Como he dicho estos ficheros son editables con cualquier editor de textos, en mi caso utilicé el bloc de notas. 
  • Hacemos una copia del fichero KML, pongamos pru.kml, y la abrimos con el bloc de notas.
  • Eliminamos todas las líneas de comandos y nos quedamos solo con la enorme línea con los puntos de la ruta.
  • Delante de esa línea insertamos <table><tr><td>
  • Como en este caso el separador de los puntos de la ruta es un espacio sustituimos ese espacio por <tr><td>. Accedemos a la utilidad de reemplazar, escribimos un espacio en la casilla "buscar" y <tr><td> en la casilla "reemplazar por". Pulsamos reemplazar todo.
  • Añadimos después de la línea con los puntos </table>
  • Guardamos el fichero con "Guardar Como" cambiando la extensión del fichero a HTM. Pongamos pru.htm
  • Con el botón derecho del ratón (botón secundario) abrimos este fichero htm con excel. Por lo menos en mi PC funciona, ya tenemos la línea convertida en columna.
  • Copiamos la columna, con pegado especial-> Valores, a un libro nuevo.
  • En este punto hay que separar los distintos X,Y,Z de cada punto. Con Datos->texto en columnas los vamos a separar.
  • Seleccionamos la columna completa. Datos->Texto en columna, delimitados. En este caso el separador en una coma.
  • A la hora de convertir un punto de formato no vamos a tocar ni el valor X ni el Y. El valor Z lo tenemos que convertir a pies, por lo que tiene que ser numérico.
  • En el paso 3 de la conversión seleccionaríamos los dos primeros campos (X e Y) como texto y par el tercero, la altura, lo dejamos como "General" y con la opción avanzadas indicamos que el separador decimal es un punto y el separador de miles es una coma. Indicamos la celda de destino y finalizamos.
  • Para pasar la altura de metros a pies divido la altura en metros por 0,3 y ya de paso redondeo el resultado. Utilizo  la función =REDONDEAR(C1/0,3;0) 
  • El resto es concatenar los distintos valores XYZ para que tengan la estructura de los distintos formatos OZIEXPLORER o GPX.
  • Añadimos los valores en los ficheros de texto que tengamos preparados con cabeceras y colas, y ya podemos funcionar.
Conversión de De PLT a GPX
Conversión de GPX a PLT
http://ellibrosobreexcelquenoescribirenunca.blogspot.com.es/2011/11/de-gpx-plt.html
http://ellibrosobreexcelquenoescribirenunca.blogspot.com.es/2011/11/de-gpx-plt-ii.html
http://ellibrosobreexcelquenoescribirenunca.blogspot.com.es/2011/11/de-gpx-plt-iii.html