Xwork's Blog

The lord is waiting to take your hand.

Vamos a platicar #6 - Luchando contra la estupidez (otra vez).

No hay comentarios.
Hola de nuevo a todos, el día de hoy vamos a platicar otro poco acerca de cómo manejar la estupidez de los demás.


Cómo muchos de ustedes sabrán, actualmente vivo en algún lugar de la zona centro de México, por lo que son muy comunes lo movimientos telúricos. Desde aquel 19 de septiembre, estos han dado mucho de que hablar. En algunos de los post anteriores ya he expresado mi total desagrado hacia las personas que a raíz de esto, han tenido material suficiente como para decir cosas realmente sin sentido.

Solo para recapitular, desde el 19 de septiembre del 2017, se han suscitado al menos 5 alarmas sísmicas. Una alarma sísmica, en teoría se dispara cuando hay un movimiento mayor a 5°, pero de estas cinco últimas, solo dos han sido de magnitud mayor a 6°, Un problema surge de todo esto, en el 60% de los casos anteriores, a pesar de que fueron sismos fuertes no fueron perceptibles por la mayoría de la población, lo que ha ocasionado un debate.

Muchos aseguran que la alerta sísmica debería de sonar solo cuando hay temblores mayores a 6. Otros (cómo yo) aseguran que el sistema actual es el más optimo, puesto que realmente cómo saber si va a haber afectaciones o no.


En experiencias pasadas, yo también he caído en ideas erróneas: "No fue de 5, fue cómo de 7" pero para mi fortuna, he estado rodeado de gente que me explica cómo es que funcionan algunas cosas y la mayoría de ellas coincide, aún un sismo de 5° puede causar estragos. Prueba de ello fue lo que pasó en los sismos de septiembre del 2017; uno de ellos de 8.2° y otro de 7.1°; el que mas estragos causo en la zona donde vivo, fue el de 7.1. A lo mejor es un poco repetitivo, pero hay que decirlo hasta el hartazgo; hay muchos factores que determinan que tan destructivo es un sismo, por lo que solo catalogarlo por su intensidad, podría no reflejar lo que a nosotros nos interesa, es decir que tanto nos afecta.

fechahoralatitudlongitudprofundidad (km)magnitudlocalizaciónfecha utchora utc
11/04/201802:30:3815.55-95.02165.573 km al sur de salina cruz, oax11/04/201807:30:38
19/02/201800:56:5716.25-97.7710632 km al sureste de pinotepa nacional, oax19/02/201806:56:57
16/02/201818:36:5215.93-97.97165.946 km al sur de pinotepa nacional, oax17/02/201800:36:52
16/02/201817:39:3816.25-98.03127.211 km al sur de pinotepa nacional, oax16/02/201823:39:38
09/02/201808:05:4618.76-104.93165.965 km al suroeste de cihuatlan, jal09/02/201814:05:46
19/01/201810:17:4526.66-111.1166.376 km al noreste de loreto, bcs19/01/201816:17:45
03/11/201705:52:0618.7108-106.519165.6214 km al suroeste de cihuatlan, jal03/11/201711:52:06
13/10/201719:20:5716.004-95.0698635.524 km al sureste de salina cruz, oax14/10/201700:20:57
28/09/201723:00:2014.6185-94.3575165.5171 km al suroeste de pijijiapan, chis29/09/201704:00:20
24/09/201705:06:0815.0823-94.3375155.8127 km al suroeste de tonala, chis24/09/201710:06:08
23/09/201707:53:0416.496-95.146226.19 km al suroeste de cd ixtepec, oax23/09/201712:53:04
23/09/201705:38:0515.2525-94.586355.8122 km al sureste de salina cruz, oax23/09/201710:38:05
19/09/201713:14:4018.3353-98.6763387.19 km al noroeste de chiautla de tapia, pue19/09/201718:14:40

La tabla anterior muestra los eventos sísmicos mas relevantes ocurridos desde el 19 de septiembre del 2017. Si los contamos, veremos que son 13 eventos y de los cuales 5 (por fortuna) han sido mayores o iguales a 6.0 y de todos los anteriores y exceptuando el primero (de abajo hacia arriba), solo en 5 ocasiones (o al menos las que yo recuerdo) se ha activado la alarma sísmica.

El evento más reciente que activo la alerta sísmica fue el 20 de mayo del 2018, con na intensidad de 5.6, no fue perceptible por la mayoría de la población pero la alerta sísmica sonó y cómo de costumbre se hizo lo que marcan los protocolos. Tras hacer lo que se tenia que hacer y no percibir nada, mucha gente salio a insultar al sismológico nacional, algunos diciendo que no debería de activarse la alerta en sismos menores a 6 y otros diciendo que se sintió mas fuerte y que la información provista estaba mal.

Recuerden, me encuentran como @Mpm88G en twitter.
Se que hay que ser muy débil del cerebro para insultar a alguien por Internet, pero cada vez que veo este tipo de cuestionamientos/planteamientos tan tontos, me dan ganas de alejarme del internet y no es por exagerar, pero cada vez mas se puede ver este tipo de gente que no tiene idea de cómo funcionan las cosas y se pone a decir como si en realidad supieran. En cada lugar y por más serio que sea el asunto, siempre se aparecerá alguna clase de idiota, que lejos de aportar algo, simplemente acusa (mira a los terraplanistas). Al igual que en algunos de los otros post en los que he expresado mi desgrado por este tipo de cosas, también es importante marcar los limites entre donde enseñar u orientar a la persona y donde simplemente recurrir a los insultos (cómo en la imagen).

Y bien, por a hora es todo. Si quieres saber un poco más sobre la sismicidad en México, siempre puedes ir a lugares cómo el sismológico nacional, ahi fue donde extraje la tabla anterior y hay mucho material para que tu mismo saques tus conclusiones.

EDIT: Este post originalmente se debió de haber publicado el 20 de mayo del 2018, pero no lo programe bien. Igualmente creo que la información es válida no importa cuando se lea.

Los leo luego.

No hay comentarios. :

Publicar un comentario

Vamos a programar #53 - Errores y cómo tratarlos en c#

No hay comentarios.
Hola de nuevo a todos, el día de hoy vamos a ver un poco acerca de cómo se tratan los errores en c#.

En repetidas ocasiones, he dicho que siempre que se crea código nuevo, por más que uno lleve años programando, siempre apareceran errores. Algunos tan sencillos cómo "¡Olvide una coma, un punto, importar un espacio de nombres!", otros no tan sencillos o que se haran presentes hast que se ejecute el programa en la computadora del usuario final.

El programador dispone de muchos mecanismos para reportar los detalles de las operaciones que se realizan. Algunas son tan simples cómo mostrar una caja de mesaje diciendo si la operacion se llevó a cabo de manera correcta o no y otras un tanto más complicadas cómo BSOD (blue screen of death)
Solo en tiempos recientes se ha cambiado el aspecto "temible" de antes
En el caso particular de C# (y .NET en lo general), dentro del lenguaje de programación se ofrecen las herramientas necesarias para poder manejar los errores. Antes de empezar a ver cómo se debe hacer el tratamiento, debemos de tomar en cuenta el tipo de error que se produce. Siempre habrán dos tipos de errores; uno será aquellos en los que se pueda continuar con la aplicación a pesar de que se ha producido y otro (y más grave), serán aquellos en los que ya no se puede continuar.

En este caso solo nos vamos a centrar en lo errores que son producidos por Software (código), imaginemos que tenemos un fragmento de código cómo el que sigue:

private void button1_Click(object sender, EventArgs e)
{
		int j = 0;
		int I = 100 / j;
}

A pesar de que el error es realmente inminente, si ejecutamos la aplicación y además hacemos click en botón, aparecerá un mensaje cómo el siguiente:
Si hacemos clic en continuar, la aplicación tratará de continuar, pero si no le es posible, simplemente mostrará el mensaje una y otra vez hasta el final de la ejecución (o en este caso, cada que se haga clic). Si hacemos clic en el botón salir, la aplicación se cerrará y la ejecución terminará.

Actualmente hay un debate muy fuerte en la comunidad de programadores. Cuando hay este tipo de errores, es decir cuando sabemos van a pasar, ¿es necesario crear un manejador de errores en este caso? Lo ideal sería evitar que se realice cualquier división entre cero, pero por mas repetitivo que suene, nunca es posible prever todas las variables.

Manejando los errores.

El objetivo del post es ver cómo tratar lo errores en .NET (c#), asi que veamos el siguiente código:

private void button1_Click(object sender, EventArgs e)
{
	try
	{
		int j = 0;
		int I = 100 / j;
	}
	catch(Exception Err)
	{
		MessageBox.Show(Err.Message+"\n En: "+Err.Source, "MDev 2018",MessageBoxButtons.OKCancel,MessageBoxIcon.Error);
	}
}

Es exactamente el mismo, solo que ahora agregamos las palabras reservadas try y catch. Todo el código que queremos ejecutar, lo debemos de poner dentro de try, en el caso del código anterior, la división la ponemos aquí, cuando se produce el error, toda la parte dentro del bloque catch, es la que se ejecutará y para este ejemplo, mostrará una caja de mensaje.
En su forma más simple, el bloque catch, se puede escribir sin los parámetros, pero si queremos obtener detalles acerca del error, creamos una variable del tipo Exception que posee algunos detalles del error.
Dependiendo del tipo de error, se puede definir un bloque catch diferente, al código anterior agreguemos un bloque catch pero con el error que esperamos, es decir: DivideByZeroException, al ejecutar el código en lugar de ver la caja de mensaje con el icono de error, veremos la que definimos cuando se produce DivideByZeroException.

private void button1_Click(object sender, EventArgs e)
{
	try
	{
		int j = 0;
		int I = 100 / j;
	}
	catch(DivideByZeroException)
	{
		MessageBox.Show("No puede divir entre cero");
	}
	catch(Exception Err)
	{
		MessageBox.Show(Err.Message+"\n En: "+Err.Source, "MDev 2018",MessageBoxButtons.OKCancel,MessageBoxIcon.Error);
	}
}

El resultado

Finalmente, en algunos casos aun cuando se produjo el error, debemos de liberar los recursos que se usaron (o cerrar archivos), para eso se dispone de la palabra reservada finally todo el bloque de código que contenga, es el que se ejecutará al final y usualmente se usa para este fin

Cómo ya lo mencioné, es importante decidir cuando es importante tomar medidas en caso de que un error ocurra, pero imaginemos que tenemos un formulario y en el una caja de texto en la cual el usuario ingresará su número de teléfono; es bien sabido que cualquier número telefónico esta conformado por números, entonces si al hacer las comprobaciones, notamos que hay algo que no es un número, de inmediato sabremos que algo no está bien y lo adecuado sería mostrar un mensaje informado de ese detalle y no hacer un manejador solo para ese error.

Y bien, por ahora es todo.Existen muchas maneras de tratar los errores pero con las vistas aquí, es más que suficiente, errores más graves requieren otro tratamiento, pero no suelen ser comunes.

Los leo luego.


No hay comentarios. :

Publicar un comentario

Vamos a programar #52 - Introducción al paralelismo (Básico)

No hay comentarios.
Hola de nuevo a todos, el día de hoy vamos a ver cómo es que se usan las clases en .NET para poder usar el paralelismo.

Antes que nada, ¿que es el paralelismo?

El paralelismo es una forma de computación en la cual varios cálculos pueden realizarse simultáneamente,​ basado en el principio de dividir los problemas grandes para obtener varios problemas pequeños, que son posteriormente solucionados en paralelo. Hay varios tipos diferentes de paralelismo: nivel de bit, nivel de instrucción, de datos y de tarea. El paralelismo ha sido empleado durante muchos años, sobre todo para la Computación de alto rendimiento. Wikipedia/paralelismo.
 Aplicado a los términos de la programación tradicional, el paralelismo significa crear varias tareas que se ejecutan de forma simultanea, en el caso de los sistemas de computo moderno, la gran mayoría de ellos disponen de más de un procesador (9~12 núcleos en el mejor de los casos para el computo casero), pero a la hora de hacer cálculos, al menos en mi caso, nunca me preocupe por usar el mayor poder de computo disponible.

Todas las tareas las hacia de forma secuencial (una tras la otra), pero si el hardware puede hacer más, ¿porque no explotarlo cómo se debe? Actualmente los lenguajes de programación de .NET, disponen de una clase que ayuda a la hora de crear los procesos paralelos.

Para darnos una idea de cómo implementarlo, veamos el siguiente código.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;

namespace PruebaParalelo
{
	public partial class FrmMain : Form
	{
		private FileInfo[] Archivos;

		private string GetMd5(string filename)
		{
			StringBuilder SBuild = new StringBuilder();
			using (var md5 = MD5.Create())
			{
				using (var stream = File.OpenRead(filename))
				{
					byte[] Data = md5.ComputeHash(stream);
					for (int i = 0; i < Data.Length; i++)
					{
						SBuild.Append(Data[i].ToString("x2"));
					}
				return SBuild.ToString();
				}
			}
		}

		public FrmMain()
		{
			InitializeComponent();
		}

		private void BtnAddFiles_Click(object sender, EventArgs e)
		{
			string Path;
			using(FolderBrowserDialog FolderDialog = new FolderBrowserDialog())
			{
				FolderDialog.Description = "Selecciona un folder con archivos";
				if (FolderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
				{
					Path = FolderDialog.SelectedPath;
					DirectoryInfo di = new DirectoryInfo(Path + "\\");
					Archivos = di.GetFiles("*.*", SearchOption.AllDirectories);
					foreach (FileInfo Archivo in Archivos)
					{
						LVFiles.Items.Add(Archivo.FullName);
					}
				}
			}
		}
		
		private void BtnParallel_Click(object sender, EventArgs e)
		{
			string[] HASH2;
			int ItemCount = Archivos.Length;
			HASH2 = new string[Archivos.Length];
			int j = 0;
			try
			{
				Parallel.For(0, ItemCount, (i) =>
				{
					HASH2[i] = GetMd5(Archivos[i].FullName);
				}
				);
				foreach (FileInfo Archivo in Archivos)
				{
					LVFiles.Items[j].SubItems.Add(HASH2[j]);
					j++;
				}
			}
			catch
			{
			}
		}
	}
}


Para poder usar las funciones de paralelismo, debemos de importar el espacio System.Threading.Tasks. El código simplemente calcula el número MD5 de un archivo, pero si no fijamos con detenimiento en BtnParallel_Click, veremos que hacemos uso de Parallel.For , que en su forma más simple, recibe 3 argumentos. El primero, es un valor del tipo int que servirá para indicar desde que número empezaremos la iteración, en este caso es el número 0 (porque desde ahí vamos a empezar a contar). El siguiente parámetro, también es un valor del tipo int, que se usará cómo limite para la iteración, en el caso del código anterior, indicamos que solo va a llegar hasta ItemCount que almacena el número de elementos que contiene un arreglo. Finalmente viene la acción, en este caso la creamos por medio de una expresión lambda en la cual decimos que por cada elemento, se va llamar a la función GetMd5, y a su vez el valor resultante se asignará a un elemento de la matriz HASH2, cuando termine el proceso, todos los valores se agregaran al listview principal y se mostrarán al usuario.

Los resultados los podemos ver en la siguiente imagen (hablando de rendimiento).


Mientras que de un lado tenemos que el uso del CPU está en 25% y tardo 30 segundos en calcular el HASH de algunas imágenes, del otro vemos que el uso del CPU es al 100% y además el tiempo que le tomo fue una cuarta parte del tiempo del calculo secuencial.

Para que revises bien el código, lo pongo en mi dropbox cómo de costumbre, pero cabe aclarar que es meramente ilustrativo, pero cómo introducción funciona. En futuros post veremos cómo hacer uso de las sobrecargas que tienen la misma función Parallel.for, pero además veremos cuales son las diferencia con el multi-therad tradicional (recuerdo que hice un post pero no se publicó y desapareció).

Los leo luego

No hay comentarios. :

Publicar un comentario