28 jul 2010

expresiones condicionales, matemática boleana.
_____________________________________________________

Teniendo presente todo lo anterior se pueden crear algoritmos lineales, que empiezan en un punto, hacen un número de
operaciones y terminan. Ésto es muy útil, pero en realidad necesitamos más cosas para poder procesar todo lo necesario
de forma adecuada. Algo muy importante en éste aspecto es, por ejemplo, las expresiones condicionales, bucles,
interrupciones, negaciones etc

Pero recordemos nuestro punto de vista respecto a la programación, desglobando cada problema desde su base damos con
los responsables físicos de todos éstos comportamientos. Las puertas lógicas. Una puerta lógica es un elemento, normalmente
electrónico que tiene una o dos entradas y una salida normalmente. A las entradas puede llegar un cierto voltage que
interpretaremos como un true o false boleano, y la salida puede emitir un valor boleano que dependerá de las entradas, es decir:

in ----|>
      |>>
      |>>>>---- out (dependiendo de los dos in)
      |>>
in ----|>



in ----|>------ out (dependiendo de in)

Entonces, algunos tienen un in y un out, lo que significa que crea un dato que dependerá de la entrada y lo envía en
out, sin embargo, otros tipos trasforman dos boleanos en uno, dependiendo de las entradas. vamos a explicarlo paso
a paso para el que no sepa mucho de lógica electrónica. Veamos que tipos hay y para que sirven.

Usaremos un sistema muy común para representar los comportamientos de las puertas lógicas, la tabla de verdad.
Si no sabes como funciona, tranquilo, porque es más simple que rascarse la naríz. Se trata de una taba en la
que ponemos las dos entradas y la salida de la puerta logica de esta forma:

ejemplo:la tabla de verdad de una puerta XOR es:
entrada+entrada=salida

1+1=0
1+0=1
0+1=1
0+0=0

recuerda que usamos + pero no el matemático, es un simbolo que significa "con esto y esto es igual a esto" o sea:

con un uno y un uno es igual a cero.
o tambien se puede expresar a través del tipo de puerta, o sea:

1 XOR 1 = 0
esto significa

true o (exclusivo) true es igual false?; o, uno, cero. ¿está activado sólo uno de los dos? respuesta= no (cero)

Por lo tanto la tabla de verdad es algo parecido a recorrer todas las posibilidades que nos dá una puerta lógica según sus entradas, guardando sus salidas.


los tipos básicos son estos

puerta YES: La puerta yes tiene una entrada, y siempre devuelve el mismo valor que entra. Existe principalmente
como amplificador electrónico, así que no afectará en los algoritmos directamente, sino únicamente
en la capa física. Éstas puertas lógicas se las dejamos a los ingenieros electrónicos.

in -----|>----- out = in

tabla de verdad:

 1=1
 0=0

puerta NOT: Esta puerta lo que hace es devolver el inverso boleano de la entrada. O sea, el negativo del valor, si
tenemos uno da cero y si tenemos cero da uno.

in -----|>----- out = NOT in

tabla de verdad:

 1=0
 0=1

puerta AND: Interesante, ya que devuelve un uno cuando las dos entradas son verdaderas, o sea, que sirve para comparar
dos valores boleanos y dice true solo si las dos son true. Ok, ésto es básico en programación general,
ya que como bien dice el título de éste tema, trataremos las condiciones, es decir, haremos que nuestros
sistemas tengan capacidad para elegir una u otra acción. Y ésto se hace, ni más ni menos que con
puertas lógicas combinadas. Se explicará luego, pero tienes que entender las puertas de más de una
                entrada, si hace falta lee en internet, en alguna enciclopedia, libros de electrónica... en serio.

inA -----|>
        |>>--- out = inA AND inB
inB -----|>

De esta tenemos que hablar más ya que es una pieza clave como vengo diciendo. Un electricista se
habría percatado de que la tabla de verdad de ésta puerta lógica equivale a un circuito simple
con dos interruptores en serie. Exacto, de hecho éso mismo son las puertas lógicas, y por eso mismo
llamamos interruptor a una cifra boleana, y no número. veamos el esquema de otra forma:

 inA          inB
 ____      ____
true -----:  :--------:  :----- out = inA AND inB

-en este esquema in significa bajar el interruptor. Entonces tenemos un true continuo, lo que
viene a ser una fuente de energía, y el cable está cortado por dos interruptores
convencionales. En out sólo tendremos ésa energía si pulsamos los dos interruptores al
mismo tiempo, pulsar uno independientemente es inútil. Posiblemente un electricista lo
vea así más claro, pero exísten relacciones matemáticas y algorítmicas, que son las que
aprobecharemos.

tabla de verdad: -bien, tiene dos entradas boleanas, medio nibble. Asi que tenemos cuatro opciones.

1+1=1
1+0=0
0+1=0
0+0=0

Y como buscamos la relacción matemática pues interpretamos las dos entradas como medio nibble:

3=1
2=0 -o sea, nos indica si el resultado, en este caso 11 (3 dec), no cabe en un solo bit... interesante.
1=0
0=0

Visto así, parece que tiene menos sentido, pero es en realidad, lo que hace el ordenador según nuestra
interpretación, y expresado en decimal. la salida siempre será uno o cero, ya que tiene una cifra binaria.

puerta OR: Una puerta OR u "o", realiza lo que se llama "suma lógica", que es algo distinta de una suma numérica.
Tengamos en cuenta que estamos tratando con valores boleanos, así que SOLO PODEMOS USAR UNA CIFRA
para los cálculos, y ésta sólo puede ser uno o cero. Así que 1+1=1, el dos no existe, no tiene
sentido hablar de otra cifra que no sea uno o cero. Para verlo mejor, true mas true es true. Asi
mejor, ¿no? porque en realidad no son números, sino trues y falses, si o no.

inA -----|>
          |>>--- out = inA OR inB
inB -----|>

Otra vez el electricista entenderá bien el siguiente ejemplo, supongamos que tenemos una entrada
de corriente y dos interruptores en paralelo. Si pulsamos cualquiera de los dos, pues la bombilla
se enciende, lo que significa True. Si pulsamos los dos a la vez pues tambien se enciende, y
unicamente cuando se deja todo apagado recibimos un cero, o sea, oscuridad, éste es el funcionamiento
de la puerta or.

La tabla de verdad:

1+1=1
1+0=1
0+1=1
0+0=0

Y lo interpretamos en números:

3=1
2=1
1=1 -vaya, éste nos indica cuando el resultado es mayor a 0.
0=0

Y hay muchos más tipos de puertas lógicas, pero precisamente se deducen a partir de éstos. Por ejemplo, para que una puerta lógica tenga ésta tabla de verdad:

1+1=1
1+0=0 -que nos indica cuando los dos valores son iguales.
0+1=0
0+0=1

Tendríamos que conectar en paralelo cada entrada a una puerta AND y una OR. Éste tipo de puertas se llama XNOR, la x indica "exclusivo", la n NOT y su comportamiento se deduce de la OR. Es decir: AND-NOT-OR exclusivo... Pero le llamaremos XNOR.

Si un circuito en paralelo hemos dicho que es una puerta OR y queremos conectar una AND y una OR en paralelo hacemos:

-Llamamos bit1 y bit2 a las dos entradas.

XNOR=(bit1 AND bit2) OR NOT(bit1 OR bit2)

Entonces podemos deducir la tabla de verdad XNOR con estas relacciones:

(1 AND 1) OR NOT(1 OR 1)= XNOR(1+1)
(1 AND 0) OR NOT(1 OR 0)= XNOR(1+0)
(0 AND 1) OR NOT(0 OR 1)= XNOR(0+1)
(0 AND 0) OR NOT(0 OR 0)= XNOR(0+0)

Y ya tenemos un nuevo tipo de puerta lógica creada de forma matemática a partir de otras más simples. Lo que tiene que quedar claro es que cualquier tipo de puerta lógica puede combinarse dando lugar a otros tipos, por ejemplo tipos con más entradas, así como más salidas. Al final todo lo que hay en un chip para un programador son puertas lógicas y memorias. Vamos a aplicar la fórmula anterior para comprobar que funciona.

la tabla de verdad XNOR dice lo siguiente:

0+0=1

entonces si (0 XOR 0) = (0 AND 0) OR (NOT(0 OR 0))

paso por paso:

(0 AND 0)= 0 -Calculamos cada paréntesis.
(NOT(0 OR 0))= (NOT 0) -ok, los dos dan cero. Pero tenemos otro paréntesis aún.
(NOT 0) = 1 -la segunda salida. perfecto. usaremos ésta y la del primer parentesis como entradas.
para el último OR así que:
0 OR 1 = 1 -funciona-

Una puerta XNOR se puede entender como:

-es una puerta lógica de tres patillas, dos entradas y una salida.
-tiene dos pistas en paralelo. (por el OR de enmedio)
-la primera pista pasa por una puerta AND, y de ahí a la salida. (bit1 AND bit2)
-la segunda pista pasa por una puerta OR, y luego por una NOT y va a la salida. NOT(bit1 OR bit2)

Por lo tanto, (AND)OR NOT(OR) es más que una fórmula, bién leído es un mapa de puertas lógicas. Yo lo he dibujado y tiene lógica.

Espero que éste método de expresión ayude a entender un aparato de una forma distinta, ya que podemos
expresar su arquitectura interna a través de un lenguaje bastante matemático. Bueno, las operaciones de este tipo se llaman operaciones lógicas, y como ya sabes no maneja cifras, sino condiciones, verdaderas o falsas. La matemática de objetos boleanos se denomina Álgebra de boole y es en si misma la base donde se sostiene todo el sofware y las decisiones de diseño de los aparatos.

El álgebra de boole recibe el nombre de su inventor, un matemático llamado George Boole. Se le considera como uno de los fundadores del campo cientifico de la computación. Ten en cuenta que Boole murio en 1815, es decir, no llegó a conocer las computadoras y sin embargo, a través de su álgebra aprendió a simplificar y resolver problemas lógicos y filosóficos con los primeros algoritmos de nivel bajo, escritos y resueltos a papel y lápiz.

Y esque lo que Boole buscaba no era para nada dotar de capacidades aritméticas a las máquinas, sino un lenguaje algebráico a través del cual pudiera expresar problemas de lógica, no de números. Boole creó una matemática especial a través de la cual, hoy día podemos comunicarnos con las máquinas de una manera adecuada para un sistema informático. Lo que diseño boole es algo muy extenso y preciso, como matématica que es. Digamos que nosotros lo aprenderemos de una forma diferente, pero sabiendo que lo que hacemos, en todo momento, es expresable en álgebra de boole así como en hardware puro (el ejemplo de las bombillas y los interruptores, por ejemplo). El álgebra de boole, nosotros lo expresaremos a través de los efectos de los datos sobre una puerta lógica, es decir (1 OR 0) es pasar por una puerta OR un 1 y un 0, lo cual vale 1, o true.

¿Para que aprendemos todo esto? Pues para aprender de nuevo a sumar:

Bueno, ya has visto que podemos transformar boleano en diferentes cosas, por ejemplo, si lo interpretamos como binario y realizamos una suma... Espera, un binario es un monton de boleanos, y los boleanos no se pueden sumar aritméticamente. Claro, solo podemos hacer operaciones boleanas, lo que es lo mismo, transformaciones a través de puertas lógicas... o sea, tenemos que diseñar un circuito electrónico que sea capáz de sumar... Tranquilo, suelta el soldador, que lo haremos matemáticamente. Es importante tener una memoria donde se guarde el número final, y necesitamos dos entradas de un numeros
binarios.

Usaremos cuatro cifras binarias de entrada, que es un número hexadecimal de una cifra.
Son ocho entradas y cinco salidas para que nos quepa el resultado final si sumamos 16+15=31, que en binario es la quinta cifra.

creamos IN1(4), IN2(4) y OUT(4) como colecciones boleanas. Son dos entradas y una memoria o salida.
Creamos AC como boleano. tambien un boleano simple llamado AC

para sumar hay que trabajar en cada In1 e In2 en IN1() e IN2(), pero no vamos a usar un bucle, porque es pronto, así que lo haremos de forma absoluta. Es decir, un chip que suma dos números hexadecimales de una cifra y devuelve la suma en binario porque sí, porque está diseñado para responder así, no hay condiciones ni funciones ni repeticiones. Es algo parecido a una pequeña parte de un coprocesador, que ya explicaremos
qué es.

entonces, siempre haremos esto:

OUT(0)=(IN1(0) XNOR IN2(0)) -metemos en out un nor exclusivo de las primeras cifras.
así sólo dará uno si una u otra está activada, pero no si lo están las dos.

AC= (IN1(0) AND IN1(0)) -AC guarda un and, si están las dos éste es true. És lo que llamaremos el
"acarreo", igual que en matemática clasica, nos llevamos una, esta se usará luego


OUT(1)=(AC XNOR (IN1(1) XNOR IN2(1))- Calculamos el xnor, y hacemos otro xnor comparando con AC, la que nos llevamos.
AC= (IN1(1) AND IN1(1))    - Guardamos el acarreo, y ya repetiremos hasta el final lo mismo.

OUT(2)=(AC XNOR (IN1(2) XNOR IN2(2))-Calculamos xnor y xnor con el acarreo
AC= (IN1(2) AND IN1(2))    -Guardamos el acarreo dentro de AC

OUT(3)=(AC XNOR (IN1(3) XNOR IN2(3))-Calculamos xnor y xnor con el acarreo
AC= (IN1(3) AND IN1(3))    -Guardamos el acarreo dentro de AC

OUT(4)=(AC XNOR (IN1(4) XNOR IN2(4))-Calculamos xnor y xnor con el acarreo
AC= (IN1(4) AND IN1(4))    -Guardamos el acarreo dentro de AC

OUT(5)=(AC)             -La ultima cifra corresponde al último acarreo solo


Y tenemos un algoritmo en el más básico de los niveles que podemos elegir. Puedes darles valores a las entradas y calcular cómo funciona. La tabla de verdad de ésta circuitería es enorme, y correspondería en decimal a 1+1=2, 1+2=3, 1+3=4, y así hasta el número máximo de combinaciones que podemos lograr, en binario usando cinco cifras el valor máximo de respuesta es 31. Éste pequeño chip o pequeño programa en ensamblador, o pequeño circuito eléctrico es una calculadora que sólo sabe sumar números en binario, ya con ésto podrías construirla, si le añades entradas y salidas (botones, leds, pantalla...). Pero podría ser otra cosa tambien, una Funcion. Las funciones son grupos de acciónes que normalmente devuelven un valor. Se usan en casi todos los lenguajes que no correspondan al nivel bajo, y algunos que si. Cuando mandamos sumar a una máquina, ésta hace lo que has visto arriba con las cadenas boleanas (que son numeros sin interpretar). O sea, ¿Para que construir la máquina si tenemos un ordenador que puede ser entrada y salida a la vez? ademas, un ordenador tiene un conjunto de interfaces muy bien diseñados, como por ejemplo los sistemas operativos, consolas de comandos o lenguajes de programación.

Con la fórmula anterior podemos sumar... puede que prefieras el método clásico para hacerlo, pero la máquina no, ella siempre suma de ese modo, y por eso es bueno saber que lo hace así. Y hay que entender que se puede hacer de diferentes formas, ya que XNOR= NOT XOR Y XOR= OR OR AND. Se que parece complicado verlo a primera vista, pero todo tiene una lógica tan bien estructurada que al final se entiende por su propio peso. el algoritmo anterior, expresado matemáticamente sería tan solo:

creamos IN14, IN24 y OUT5 como numeros binarios. Son dos entradas y una memoria o salida.

OUT5 = IN14 + IN24

Vaya parece más simple... Claro, el poder procesar los datos así automáticamente es tambien resultado del diseño de interfaces manejables. Los viejos ordenadores que usaban targetas perforadas, sólo entendían entradas en boleano y respondían con ellas. Podía resultar complicado en aquel momento procesar una simple suma, ya que tendrían que recurrir a sistemas parecidos al expuesto arriba. En realidad, tenemos que entender cualquier operacion matemática como una función de nivel bajo, o físico que produce un resultado. Así seremos conscientes de que lo que escribimos en un código fuente NO es lo que procesa el ordenador exáctamente. El problema que tenemos para entender esto surge de que nosotros sumamos "casi automáticamente", parece como si no tuvieramos consciencia de cómo sacamos el resultado, pero sale, y no analizamos paso por paso el problema, porque no nos hace falta.

Desglobar un problema es la manera de entenderlo, y la mejor manera es reduciendolo al menor número de símbolos, lo cual produce una mayor cantidad de pequeños pasos. En el caso de la suma, hay una forma de automatizar el proceso, que consiste en realizar la misma acción en cada línea. Entonces podemos decir que:

Donde pun indica el puntero en el que realizamos la acción, es decir, la posición de la cifra que queremos calcular.

OUT(pun)=((IN1(pun-1) AND IN2(pun-1)) XNOR (IN1(pun)XNOR IN2(pun))

Así que cada vez que sumes un número recuerda: ((IN1(pun-1) AND IN2(pun-1)) XNOR (IN1(pun)XNOR IN2(pun))=
         
Pero es un algoritmo no diseñado aún para estar dentro de un chip de memoria, sino que utilizamos matrices virtuales. En un caso real no sería buena idea usar un chip de memoria para cada número, sino darles una dirección en la matriz principal, que será toda la memoria del programa. Es decir, que podemos diseñar nuestra placa de tal forma que todos los números se encuentran en el mismo chip de memoria, a parte necesitamos las mismas puertas lógicas, pero no son muchas. Ésta forma de escribir un algoritmo lineal con puertas lógicas nos permite entender por un lado cómo suma realmente una máquina, pero además es un mapa de un circuito de puertas lógicas, sólamente hay que saber descifrarlo paso por paso.

Para hacer un plano de puertas lógicas:

(entrada1 OR entrada2)=salida1. -significa:

tenemos una puerta OR conectado a dos entradas, entrada1 y entrada2 y a una salida que se llama salida1. Parece un órden extraño, pero míralo de otra forma. Cuando veas una puerta lógica, en este caso OR, el elemento de antes y de despues son las dos patillas de entrada, y el iguala de despues del parentesis es la salida (o sea, que decimos dónde va a parar el dato). Si tenemos un parentesis doble, por ejemplo: (in1 OR (in1 AND in2)) empezaremos siempre por lo de dentro de los paréntesis, o sea, (in1 AND in2) que significa una puerta AND con entradas conectadas a in1 e in2. (in1 OR ...) Pueden ser dos cosas, una puerta or, que por un lado tiene conectado in1 y por otro la salida de la puerta AND de antes (in1 AND in2). O si no se puede entender como el modo en que se conecta el circuito: AND=serie, OR=paralelo. Así que podemos decir que in1 va directo a la salida y además está en paralelo con una puerta lógica que tiene de entrada in1 e in2. El comportamiento de las dos placas es el mismo exáctamente. El mapa codificado no define si vamos a usar una puerta lógica o una estructura de pistas, porque es "virtualmente" lo mismo. En este caso no salen, pero cuando una puerta lógica sólo tiene una entrada, se pone primero la puerta y luego la entrada, es decir: (NOT in1)= y la salida es por el =. Ahora veamos otro ejemplo de placa:

(bus1 OR (bus5 AND (NOT bus7)))

tenemos una puerta OR conectada con dos entradas, una es bus1 y otra es la salida de una puerta and, que tiene dos entradas, bus5 y una puerta not conectada a bus7, en este caso no hay salida porque no existe el =. Esto tiene un par de consecuencias, atemáticamente es una expresión que no se guarda en ningún sitio, podria servir como sentencia, que ya explicaremos lo que significa, y por otro lado, físicamente podemos decir que se trata de un circuito sin acabar, o que tiene una salida desconectada, además podemos afirmar que la salida desconectada es la de la puerta OR. Y todos éstos datos están
en (bus1 OR (bus5 AND (NOT bus7))), pero hace falta pensar sobre ello un buen rato.

Así que, combinando memorias, numeración binaria y álgebra de boole conseguimos... Un Ordenador. Cualquier expresión que pudieramos escribir en su forma de fórmula con puertas lógicas es computable con un ordenador común, lo que normalmente se llama touring completo. Tambien se pueden añadir memorias a nuestro mapa-fórmula, definiendolas como boleanos, o matrices boleanas; usamos un boleano para indicar un solo bit, o un interruptor, y una matriz para indicar una memoria en el mismo chip, o un bus con varios bits boleanos de ancho de banda, es decir, varios bits de entradas que forman parte de lo mismo. Si diseñamos un programa es lo mismo, solo que la placa de memoria que usamos, es el trocito que el sistema operativo nos asigne. Su tamaño dependerá de los requisitos del propio lenguaje, o sus propias convenciones.

Sabiendo ésto nos queda otra pieza clave, más que nada una pieza algorítmica, o lo que se llama de "flujo del programa", se trata de los saltos de línea. A través de complejos diseños de puertas lógicas y/o de funciones se consigue indicar a un programa, que "salte" hasta donde le indicamos, dando igual que dicho punto se encuentre arriba o abajo en el código, ya que ésto sólamente significa alante o atras en la memoria ram, o pun>label o pun

Trata de imaginar uno de esos libros de "elige tu aventura", de esos que dicen "salta a la página 23 para matar al mono" o "salta a la pagina 12 para empezar a programar". Pues la idea básica de estos libros es la misma que la de un programa de nivel medio o alto. Lo que hace es:

1- poner el programa entero en la ram (incluyendo los números o char que creemos)
2- comenzar a leer por el "cuerpo" del programa, linea a linea hacia abajo
3- de vez en cuando hay un "goto siguiente" o "goto fin" que quiere decir ve a siguiente, o ve a fin.
4- todos los programas son finitos, como los libros, así que despues de saltar alante y atras siempre encuentra una salida y fin.

El sistema con el que lo vamos a explicar es el mismo que usan el quickbasic y el visual basic. Ya que acostumbrandote a visualbasic podrás diseñar programas de muy alto nivel capaces de aprobechar tu sistema operativo así como tus capacidades de conexión a periféricos. Un lenguaje muy documentado, del que encontrarás comunidades y ejemplos en internet, y con un sistema de ayuda para principiantes que te enseñará mejor que cualquier universidad. Para saltar a una línea lo que tenemos que hacer es goto [label] y tiene que existir en el programa un punto que se llame label:. Por supuesto cambias label por la etiqueta que mejor te venga.
ejemplos:

creamos num1 y num2 como numeros hex -tenemos dos nibbles, y cada uno de ellos es un número.

num1=1h -aquí num1 vale 1h, y num2, como no tiene valor "null", que significa nada.

goto fin -decimos salta a la etiqueta fin.

num1=fh -aqui num1 debería de cambiar a fh
num2=dh -aquí num2 debería de cambiar a dh
fin: -esta es la etiqueta fin. goto fin significa venir hasta aquí y procesar hacia abajo.

exit

Y nuestro programa ha terminado, ahora si miramos qué hay dentro de num1 y num2:

num1=1h
num2=null

Porque ha saltado los pasos num1=fh y num2=dh cuando se ha dicho goto fin. Fin podría tener cualquier nombre, pero el exit del final significa que el programa ahi termina, es una palabra reservada, como goto, o creamos. O sea, a partir de ahora, cuando escribamos un codigo con fin, éste se llamará exit. Conociendo los saltos goto, que son algo simple, podemos conectar ésta pequeña placa a otras puertas lógicas. Hay una muy interesante, que es una combinación compleja que usa los saltos de línea, ésta es la condición if:

If significa "si" condicional, no de afirmación. Es muy simple, una puerta lógica de una sola entrada y dos o tres salidas, que están conectadas a saltos de línea. Como es una puerta lógica que solo tiene una entrada, se escribe antes que su entrada. La entrada de una puerta if se llama sentencia, y se trata siempre como conectada a la entrada de if, aunque se tenga un igual a "=", ya que entonces significa comparar, y si son identicas pues manda true. O sea, el iguala sería otra puerta lógica que compara. Un ejemplo sería este:

If (Ent1 AND Ent2) -que significa: una puerta if conectada a una AND que tiene dos entradas, ent1 y ent2 nos devuelve true.


Pero if a su vez tiene salidas, unas salidas que no vemos, y van a saltos de línea. Las salidas hacen saltar a diferentes puntos, puede haber
hasta tres puntos:


if (Ent1 AND Ent2) then -then es la primera salida. si (Ent1 AND Ent2)=true pues salta hasta then. despues de cargar then, salta hasta end if

else -la segunda salida, else, en inglés "si no". salta hasta aquí si (Ent1 AND Ent2)=false. Pero else es opcional, si no está va a end if.

end if -esta es la última salida. Todos los caminos acaban saltando hasta aquí si no se dice lo contrario con otro salto.


se puede hacer tambien así:


if (Ent1) then -significa, si ent1 tiene un bit boleano en true salta a then.

end if -como no hay else, si ent1 no tiene un bit boleano salta hasta end if.

o así:

if (txt3 = txt2) then -lo cual significa que tenemos una puerta AND combinada, a la que llamaremos "=" y devuelve true si las dos entradas son totalmente
idénticas.

end if

y los símbolos =, >, <, <>, se consideran puertas lógicas complejas, que comparan números, y devuelven sólo un uno o un cero si..:

= - si las dos entradas son iguales. Funciona con texto también.
> - si la primera es mayor que la segunda
< - si la primera es menor que la segunda
<> - si son distintas es lo mismo que NOT =. Funciona con texto también.

Es decir, que son puertas lógicas de ancho de banda aparentemente indeterminado, y sólo da uno si se cumple la norma definida en todas las cifras boleanas de
entrada. Son circuiterías muy complicadas, pero muy básicas y eficientes. Ahora podemos hacer sentencias, o sea, entradas if como éstas:

if ((5 > int1*2) AND ( NOT(hex1 = hex2) )) -lo cual significa: devuelve true si cinco es mayor que int1*2 y hex1 no es igual que hex2.
-es una placa con infinidad de puertas lógicas de las básicas, además aun deberíamos de situar los puntos de salto...
end if

O sea, que podemos construir sentencias muy muy complejas para que nuestro programa sea "inteligente". Como if son puertas lógicas, se pueden combinar para dar lugar a otras, como el switch o select case, o la etiqueta elseif, ahora no los explicaré, pero verás que símplemente nos ahorran trabajo a la hora de escribir, podríamos diseñarlos a partir de if, o incluso a partir de saltos de línea en ocasiones. Como te irás dando cuenta, unas cosas se apollan en las anteriores, y nos permiten hacer cosas cada vez más complejas. Es lo que se conoce en ciencias de la información como estructura por capas. En cada capa que subes, lo que puedes hacer es más abstracto, así que al final acabas programando ventanitas y fotos con pocas líneas de texto, apollandote en todo lo que queda por debajo, incluyendo al sistema operativo, los intérpretes, interrupciones de sistema, niveles de prioridad, todo tipo de librerías que ya existen y no vamos a rehacer etc etc etc.

Bueno, poco a poco subiremos al nivel alto, pero poco a poco, porque si no, no entenderemos nada de lo que hacemos. Aprender desde abajo es mejor que aprender lo de arriba, que es la punta del iceberg y tratar de desentrañar qué es lo que todo eso significa para la máquina. No tiene sentido. Además, el nivel alto tiene muchísimas funcionalidades, clases, y procedimientos, y el bajo tiene las cuatro cosas en las que todo esto se apolla.

Tipos de variables y datos -PROGRAMACIÓN INFORMÁTICA GENERAL-

PARTE 2:

tipos de variables y datos
_____________________________________________________

-A partir de ahora trataremos las posiciones de memoria en hexadecimal, sin embargo las colecciones en decimal. Ésto es para simplificar, así de una mirada se sabe si lo que tenemos delante es una colección de números de tamaño variable num(5), o un registro dentro de un chip MEM(0050h). De esta forma relaccionaremos la matemática diréctamente con la informática y la electrónica. Digamos que "calcularemos como una máquina". Utilizaremos nuevos conceptos, o mejor dicho, nuevas formas de usar conceptos anteriores, en especial las colecciones. A partir de ahora tendremos subcolecciones, que en realidad son una parte de la memoria, indicada por dos punteros, inicio y fin, se expresará así:

si Mem(fh) es una matriz boleana

sub(mem(5h,8h))  es igual a una colección que va desde 5h hasta 8h. Por ejemplo:

si los valores contenidos en mem son éstos:

1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | -esto viene a ser un stream o una colección de boleanos, que es casi lo mismo.

sub(mem(1h,4h)) devuelve 1110 porque son los valores de mem(4h), mem(3h), mem(2h) y mem(1h). lo puede devolver como colección de bits o como número
binario si así se indica.


Además, en este capitulo se empezará a usar el tipo texto. Es un tipo que representa un número de base 127. Si, lo oyes bien, el texto ahora es un número. Pero tranquilo, porque, normalmente, no sumaremos letras, sino que las concatenaremos. Para entendernos, utilizaremos el sistema ascii que viene a ser una tabla de símbolos. La unidad mínima de un texto es el char o carácter. un char es un número binario de ocho cifras, o uno hexadecimal de dos, que curioso, eh... pues no. En realidad se trata de otro ajuste de interface, ya que en binario, el último byte siempre es cero, pero una vez más es un ajuste adecuado por cuestiones de facilidad de uso.

Tambien comentar sobre el ascii, que por ejemplo, algunos sistemas como los que ejecutan Prim-os marcan siempre el octavo bit a 1, pero igualmente éste es ignorado en su interpretación. Y entender que un número es un número, y un texto que contiene un número es un texto. es decir:

1 <> "1"              -esto <> significa NOT=, y las comillas indican que 1 es texto ascii. ¿porque no es igual?

Bueno, en ascii los caracteres que significan números se representan por su valor en el primer nibble y la cadena 0011 en el segundo. por esto, para interpretar un número en ascii haremos lo siguiente:

creamos mem(8h) como boleano     -creamos una memoria de boleanos de dos nibbles, o un byte que es lo mismo.

mem()=stream("1") -declaramos que la memoria es igual al stream del texto "1", es decir, lo que significa en cadena boleana.

si miramos en la memoria:
mem():
mem(0h)=1
mem(1h)=0
mem(2h)=0 -el primer nibble indica el valor como si fuera un número binario de cuatro cifras.
mem(3h)=0

mem(4h)=1
mem(5h)=1
mem(6h)=0 -el segundo indica el valor 11, en decimal 3. Es por convención, para identificar que es un número en modo texto.
mem(7h)=0

así que el valor en número es igual al valor del primer nibble. creamos Bin(), que es una colección boleana:

bin()=sub(mem(0h,3h))
y para pasarlo a binario hacemos:

bin(&) a binario
y bin=0001 , el valor del número-char.

Así que siempre que trasformemos texto a binario haremos esto mismo, o bueno, lo hará la máquina. Todos los caracteres que no empiecen por 0011 serán ignorados, porque no son números.

Ya sabemos transformar entre las diferentes clases de datos, pero en realidad falta aclarar lo más importante, ¿qué es exáctamente un tipo de datos? Pues a nivel matemático es un casillero de un tamaño adecuado para su tipo de entrada, es decir, si entendemos que el único tipo de datos puro que existe es el boleano,del que deducimos el binario:
-utilizaremos una memoria principal, matriz boleana.

creamos mem(ffffh) como boleano -para el ejemplo vamos a crear un dato de cada tipo especificado utilizando sub, explicado arriba.
-además lo harémos sin sobreescribir ningúno, dándoles la memoria que necesitan.

un carácter hexadecimal = sub(mem(0h,4h)) -porque necesita cuatro bites para existir
un carácter ascii = sub(mem(4h,ch)) -este es un bite exáctamente, o sea lo necesario para dos hexadecimales o un char.
un carácter binario = mem(ch) -no hay que hacer sub, porque es sólo una cifra binaria, que ocupa lo mismo que el boleano.
un número entero16= sub(mem(dh,1fh)) -los números tambien tienen límite, se explica a continuación.

Y la verdad es que los tipos de datos es el primer paso para "subir" en el diseño por capas de los ordenadores actuales. Los números enteros también tienen unos límites, según la cantidad de bits que se utilizarán para crearlos, o sea, la distancia entre el puntero de inicio y el puntero del final. En este texto, contemplaremos todos los números como números matemáticos no limitados excepto si se declara lo contrario, o se llama, en lugar de número entero, número entero16,o número entero32 (indicando límite de 16bits o 32bits).

Para crear propiamente un valor de un tipo, hay que hacerlo en una memoria principal, en caso contrario, ésta no existe para la máquina, y se trata de un valor puramente matemático o de apollo.

Sub(mem(0,16))=new enteroA como entero   -significa que en la posicion de 0 a 16 se crea un nuevo valor llamado enteroA.
Sub(mem(0,1))=new interruptor como boleano -sí creamos un bit para usar como interruptor.

Lo interesante de esto es que existen diferentes formas para modificar un dato creado, aunque normalmente utilizaremos la asignación por el nombre de variable, o sea, nombredevariable=valor. Pero se puede hacer tambien así:

Sub(mem(0,15))=new ENT como número entero -creamos un número vacío que ocupa 16 bits en mem, desde el 0.
mem(0005h)=1 -modificamos añadiendo 1 en el puntero 5, es decir 32,
mem(0001h)=1 -modificamos añadiendo 1 en el puntero 1, es decir 2,
ENT=100010 -el número contenido ahora es el siguiente 100010, en decimal 34.

Todo esto nos sirve de base para entender qué es exáctamente una clase cuando hablamos de programación. Solo queda decir que en ocasiones pueden ser valores no modificables por el propio programa una vez declarados, éstos se llaman constantes en lugar de variables. Podemos observar que cualquier valor se puede traducir a una matriz boleana del tamaño adecuado para el tipo:

entero16=boleanos(16) -el tipo es similar a una matriz de 16 bits
char=boleanos(8) -en este caso de 8 bits

Y esto es muy útil, lo utilizará normalmente la máquina para ser capaz de trasformar, por ejemplo, números a texto así como stream() a cualquier tipo que se necesite. Lo interesante de usar tipos en lugar de matrices dimensionales de bits es que se evitan errores, como sumar una letra a otra letra, lo cual,posiblemente no devuelva una letra. Si el tipo está debidamente definido nuestro algoritmo efectuará las operaciones de forma adecuada. Si queremos, por ejemplo,encriptar un texto, si pudieramos usar sin problemas una matriz binaria interpretada como número binario o hexadecimal para hacer operaciones sobre estos valores y hacerlos ilegibles. Con el adecuado algoritmo devolvemos el valor a su forma inicial.

Entendiendo la importancia y la razón de ser de los tipos debemos utilizar sus propiedades en nuestro favor. Por ejemplo, limitando el tamaño delas variables al que vamos a utilizar, minimizando el desaprobechamiento de la memoria. Si trabajamos con un número que no puede pasar de 10, usaremos un número binario de cuatro cifras, un nibble... que es equivalente a un hexadecimal, la pérdida de datos será de 5 en decimal.

Cada lenguaje de programación de nivel medio-alto tiene su propia forma de interpretar las clases, pero suelen existir puntos en común. Este Texto no pretende enseñar uno o otro lenguaje (por ahora) así que se tratarán los tipos más comunes, como ya se ha dicho antes:

boleano-
binario-
entero-
hex-
hexadecimal-
char-
texto-

Normalmente hay que definir el tipo de cualquier variable, aunque algunos lenguajes utilizan un tipo genérico, en visual basic éste tipo se llama variant,y cualquier variable que no se defina en tipo se entiende que es variant. En nuestro lenguaje simplificado no usaremos variant nunca, sino matrices dimensionales de boleanos, que gracias a stream, split y (&) veremos que funciona igual.

Estamos preparados para diseñar pequeñas fórmulas para interrelaccionar los tipos conocidos:
Por ejemplo, vamos a enmascarar números para que en la memoria aparezcan como letras, y luego calcularemos cómo recuperar, o descifrar los números.

Vamos a enmascarar un número int16, lo cual ocupa cuatro nibbles, o dos bytes que es lo mismo. Así que para expresarlo en texto necesitamos dos caracteres en ascii. Pero hay un problema de diseño, ya que muchas de las combinaciónes no devuelven un texto ascii legible si sobreescribimos los dos nibbles en una letra ascii. Ésas letras no podrían ser accedidas o recuperadas como texto normal.

Lo que deberíamos hacer, es tirar de "perdida de memoria" para que funcione el sistema. De todas formas, la pérdida generada es un poco más que en una cadena de texto, incluso. Pero nos aseguramos de que al meter un número nos devuelve una letra,y al traducir ésta letra, viceversa.

Estudiando un poco la tabla ascii, especialmente las peculiaridades de los números, nos damos cuenta de que usamos dos nibbles para guardarlos, pero la primera parte siempre es igual:

Letra "0": 0011, 0000 = 3, 0

Letra "1": 0011, 0001 = 3, 1

Letra "2": 0011, 0010 = 3, 2

Letra "3": 0011, 0011 = 3, 3

La primera mitad de la derecha indica el valor del número en ascii, y la segunda siempre 3. Bueno, siempre que se trate de un número de 0 a 9 (bueno, y otros símbolos tambien, pero no los usaremos). Esto es interesante, ¿que pasa si cambiamos ése número 3 que lleva el paquetito ascii?. vamos a probar por separado.

creamos bin(8) que es una matriz boleana
Letra que es un char

letra="5" -letra ahora contiene un 5 ascii.

split(letra) a steam(bin()) -metemos letra a bin en modo stream de bits para que guardemos el valor boleano.

ahora mismo bin() contiene esto:

bin(0)=1
bin(1)=0    -por un lado, el número 5.
bin(2)=0
bin(3)=1

bin(4)=1
bin(5)=1
bin(6)=0    -por otro el número 3, que indica que es un numero en ascii.
bin(7)=0

entonces vamos a sobreescribir esa "cabecera" que siempre contiene el número 3. y vamos a hacerlo eligiendo una cabecera que exísta y signifique algo para todos los números del 0 al 9. Ahora mismo tengo a mano una tabla de símbolos ascii. Una posible elección es, por ejemplo, 0111 para letras comúnes en minúsculas o 0101 para la misma letra en mayúsculas. Usaremos la 0111, ya que se consigue sólo añadiendo una interrupcion en bin(6), o sea, haciendo esto:

bin(6)=1

y si miramos ahora el valor de bin():


bin(0)=1
bin(1)=0    -por un lado, el número 5.
bin(2)=0
bin(3)=1

bin(4)=1
bin(5)=1
bin(6)=1    -por otro el número 7, que indica que es una letra mayúscula.
bin(7)=0

entonces, ya no se trata de una letra "5" sino de una letra "U". Si probamos esto:

letra=sub(bin(0,7)) como char

ya lo tenemos: letra= "U"

Es un sistema rudimentario para cambiar de número ascii a letra de la P a la Y. Pero tambien, éste mismo sistema nos sirve para hacer una letra mayúscula:

si bin() es una matriz boleana que contiene "a"

stream(bin()) nos da esto: 0100 0001
y para hacerla mayúscula hay que cambiar el último 0100 por 0110 añadiendo en bin(5) un uno.

bin(5)=1
ahora nos da "A"

Y para hacerlo con otros caracteres es igual, es decir bin(5)=1, aunque no empiece por 0100, ya que el
ascii tambien está simplificado y por eso tiene cierta lógica o paralelísmo entre a y A, b y B y así
sucesivamente.

Estos son sistemas deficientes porque se tratan de una fórmula lineal que no tiene en cuenta ciertos factores para evitar errores. Por ejemplo, que pasaría si bin(5) ¿contiene ya un uno? pues que el char no cambia, pero procesamos ese cambio, sustituimos un uno por un uno, lo que es desperdiciar tiempo. Puede que no se note apenas, pero suponte que cada una de las letras ascii que están en tu ram, generara un proceso de éste tipo nada más entrar en ella. Igual en un ordenador viejo, o una pocket pc notaríamos algo de retardo.

Recuerda que es sólo teoría. En la práctica, el nivel bajo del ordenador está diseñado de un modo que puede evitar hacer ciertas operaciones inútiles, así como obviar ciertas cosas (no tienes que escribir en binario, pero está claro que en la memoria, el número entra en binario). Además estámos tratando el proceso informático desde un punto de vista de pequeñas memorias y procesos de nivel matemático, por lo que, mas o menos, se podrían llevar a cabo en pequeños chips electrónicos, más que en los grandes pcs. Poco a poco nos acercaremos a los procesadores grandes, que contienen diferentes "casilleros de memoria" que conforman lo que se llama arquitectura.

Pero esto es un tutorial diferente, ya que no vamos a enfocar, al principio, en ninguna tecnología específica, sino en conceptos matemáticos, o teóricos que se pueden aplicar a cualquier sistema que pueda contener y manejar memorias. La idea es explicar cómo un lenguaje, está formado por capas de diferente nivel de abstracción, pero todo empieza en una matemática muy muy basica. Cuando empieces a programar, posiblemente lo hagas en un nivel alto, pero a pesar de ello verás que trabajas con los mismos tipos, enteros, enteros largos, caracteres, strings (texto), incluso a veces tambien colecciones y colecciones de colecciones, solapadas en una estructura de objetos abstractos.

El problema es que si buscas en internet cómo programar, te enseñan a programar en uno o otro lenguaje, así aprendes tambien los vicios propios de ese mismo lenguaje y puede ser dificil deshacerte de ellos. Pero una vez se entiende cómo un procesador crea, mueve y trasforma datos en la memoria, se tiene otra visión de la programación. Poco a poco verás que los lenguajes de programación tienen paralelísmos y puntos en común, y que al fin y al cabo todo se reduce a mover datos en matrices binarias o submatrices (variables etc). Verás que los lenguajes de bajo nivel, como son el assembler utilizan además del propio procesador, partes del sistema operativo, que se encuentran en la memoria ram lo que ya no es un nivel tan bajo.

Pero por ahora sólo sabemos que un procesador hace cálculos y que una memoria guarda interruptores, ademas de crear tipos de datos, o casilleros y escribir en ellos. Aún falta entender un par de conceptos básicos para poder escribir un algoritmo. El sistema matemático está muy bien para expresar comportamientos en pequeños chips pero poco a poco adoptaremos expresiones del pseudocódigo, las cuales explicare paso a paso.

binario y boleano. interruptores y números -PROGRAMACIÓN INFORMÁTICA GENERAL-

sistema binario ,hexadecimal y su matemática
__________________________________________________________


El sistema de numeración binaria tiene una función similar a la del decimal, es decir, registrar números. Es conocido como el "lenguaje interno" de los ordenadores, bueno, en realidad es su forma de interpretar números, y dependiendo de dónde coloquemos esos números pasa una cosa u otra. Pero esto no viene al tema, lo que trataremos de explicar es el sistema numérico binario y las operaciones de matemática básica, que están muy relaccionados.

Tenemos que diferenciar entre expresiones numericas binarias y boleanas.

El sistema numerico binario es un sistema de base2, es decir, por cada unidad independiente el valor puede ser o
nulo o "1".

ejemplos:
10 =2 =1*2+0*1
10111 =23 =1*16+0*8+1*4+1*2+1*3
1 =1 =1*1
100 =4 =1*4+0*2+0*1


Una expresión boleana no representa un número, sino una opción que puede ser verdadera o falsa, un número binario se podría entender como una serie de expresiones boleanas separadas en tiempo o posición (de memoria), haciendo split(binario) a boleano().

ejemplos:
1 =si
0 =no
true =si
false =no
+ =si
- =no

y así cualquier otro símbolo que pudiera expresar dos estados diferenciados.
en este texto utilizaremos true/false o 0/1.

La relacción entre binario y boleano es muy clara, porque como he explicado antes, el binario se puede dividir en un montón de expresiónes boleanas. De hecho, las máquinas actuales, a nivel muy muy bajo, de interior del chip, no interpreta el binario porque no puede, sino que utiliza las cadenas boleanas para activar interupciones que desencadenan la trasformación adecuada de los datos. Ésto lo explicaremos a fondo poco a poco.

ejemplo:

la entrada en binario es 1011

1011= true true false true

Para diferenciar entre las diferentes expresiones hay que separarlas o referenciarlas. Les daremos una posición en una matriz y listo.creamos una matriz de 4 valores boleanos: Nb(3) -(si, el cero existe!)
entonces al trasformar el binario a boleano queda así:

split(1011) a Nb(3), que es una matriz boleana

Nb(0)=true=1
Nb(1)=true=1
Nb(2)=false=0
Nb(3)=true=1


y tenemos que entender que esto NO ES UN NÚMERO, sino un monton de interruptores encendidos o apagados. A través de una simple fórmula se puede recuperar el número. Para hacerlo matemáticamente tenemos que interpetar el boleano como una cifra que o es 1 o es 0, para hacerlo algorítmicamente lo interpretamos como verdadero o falso y creamos condiciones:

boleano a binario:

para recuperar el numero binario tenemos que concatenar los boleanos en el órden adecuado,
es por eso que se necesita usar direcciones de memoria, que en nuestro ejemplo son 
                   direcciones de puntero dentro de la matriz:

donde Nt es un numero binario
Nt=Nb(&)
Nt=1&0&1&1=1011

Nt contendrá el número total, es un número en binario, no un boleano:
Cada nb en Nb() se trasforma en un binario de una sola cifra, lo cierto es que no requiere
ninguna trasformación excepto por el trato que le damos:
Recuperaremos el valor en decimal, para entender mejor la diferencia entre interruptores o número.

Nt=Nb(0)+Nb(1)*2+Nb(2)*4+Nb(3)*8

en nuestro caso_ Nt = 1+1*2+0*4+1*8 = 11

Cuando concatenamos dos boleanos dentro de un sólo boleano lo que estámos haciendo es una condición and, que sólo devuelve 1 si las dos entradas son 1:
B1 y B2 son boleanos

donde B1=1 y B2=0, B1&B2=0
donde B1=1 y B2=1, B1&B2=1

Y ahora no nos vamos a meter con el texto, pero si concatenas un char con otro, el resultado es por fuerza un texto.

"a"&"g"&" "&"r"= "ag r"           -el resultado está en modo texto.

Hay que aclarar que "casi cualquier cosa" se puede trasformar a una cadena boleana() y recuperarla con el adecuado algoritmo, cuando hagamos esto, llamaremos a esa cadena stream, para entendernos. Por ejemplo, si trasformamos texto a un modo manejable para ser enviado por red crearemos un stream(texto) que es identico a hacer split(texto) a boleano, lo mismo para un número binario o decimal.

Un valor boleano positivo es por definición un interruptor activado. En nuestros ordenadores comúnes se entendería como una puerta lógica cerrada, un microtransistor en estado "excitado", así como un campo magnético en el disco duro, o un agujerito en la superficie de un dvd. Y esque éste es el único lenguaje que entiende la máquina, más allá de lo que nos han enseñado sobre el código binario.

Con combinaciones de puertas lógicas, o colecciones boleanas, se pueden conseguir cosas muy interesantes, por ejemplo:

si tenemos bol(4) es fácil interpretarlo cómo un número binario bin4 de cuatro cifras, lo que se conoce como nibble, esto es porque hacemos esto:

bin4=bol(&) (concatena todo en orden)

y si usamos el sistema explicado anteriormente:

creamos un decimal vacío de dos cifras: Dec2

split(bin4)   -trasformamos bin4 en matriz dimensional

por cada puntero en bin4() hacemos:

Dec2=Bin4*(puntero)  -el valor máximo de Dec2 es 99, el de Bin4() en binario es 15, así que el valor cabe en el casillero.

de esta forma, la primera pasada, el puntero es 0, y nos da el valor de unos, el segundo el puntero es 1, nos da el numero de doses y así sucesivamente.

Bien, precioso, pero es todo matemática, ¿no?. Bueno, en realidad es mucho más. Es electrónica e informática, teoria de la información y comunicaciones en parte. Me explico. Si un valor que puede ser uno o cero es tambien un acumulador de memoria de un bit, es decir, unidad mínima del chip de memoria, entonces para crear un chip que pueda memorizar un número de 0 a 15 lo que hay que hacer es colocar cuatro de éstos y diferenciarlos independientemente de algún modo. Ésto lo simplificamos así:

bin4 es el número que vamos a meter en los cuatro transistores estáticos, un binario de 4 cifras.
Chip(4) representa una matriz de valores boleanos, que es lo unico que entiende un chip.

bin4=bol(&)

Y en este caso la dirección de la memoria del dato la representamos con el puntero de bol().

Hay que entender que aunque parezca muy teórico no lo és, es una simplificación de algo que depende de muchas más cosas, como el voltage interno del chip, las resistencias, ruido electromagnético etc y lo encapsulamos en fórmulas matemáticas. bin4=bol(&) representa un comportamiento de un chip, que si le mandas un numero binario de cuatro cifras, en un lenguaje que él entienda, lo romperá y meterá cada uno o cero en un casillero adecuado.

¿Y porque cuatro? en realidad nada es al azar, si recordamos el ejemplo del ábaco, el interface es algo importantísimo, y
en este caso hablamos de un interface que no está dirigido al usuario final, sino al desarrollador de máquinas. Si utilizamos
cuatro cifras binarias, podremos determinar un número de 0 a 15, lo cual es un número redondo, si, es redondo en hexadecimal:

0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f

esta es la base del sistema hexadecimal, y si cuentas el número de cifras verás que te da 16, de 0 a 15 son 16 posibilidades,
es un interface perfecto para guardar tambien un número hexadecimal. ¿y la pérdida de memoria por el interface? Si, tambien
la hay, aunque no es mucha, me explico:

si creamos un número hexadecimal de una cifra Hex1
y tenemos una memoria vacía de un nibble Chip(4) -las memorias se entienden en modo boleano, un nibble=cuatro cifras binarias

Hex1=ch           -que significa 12, la h es para saber que es hexadecimal. en binario es 1100, como vemos son cuatro cifras, esto es, un nibble.


vemos que el hexadecimal cabe en la memoria, porque en cuatro bits caben 16 opciones, pero, si el ejemplo es menor de 8:

Hex1=5h            -el valor es 5, que en binario es 101, tres cifras. Pero al pasar el valor a boleano se crea un bit de basura. en este caso:

stream(Hex1) a Hex1() -pasamos Hex1 a una memoria boleana, stream es para trasformarlo de hex a boleano.
       -si vemos los cuatro primeros valores de hex1 en boleano:
Hex1(0)=1
Hex1(1)=0
Hex1(2)=1
Hex1(3)=0

La última posición no afecta al resultado en binario, solo existe en boleano y =false, porque no
necesita tantas cifras, y ésta es exáctamente la pérdida de memoria que se acarrea del uso de
notación hexadecimal. Se puede decir que son dos sistemas que encajan muy bien, porque sus
múltiplos son comúnes en muchas ocasiones. A pesar de que al guardar 1h estémos desperdiciando
tres veces la memoria usada, es una pérdida muy aceptable a favor de la propia interface de los
chips. El sistema hexadecimal es muy usado en punteros de memoria por ésta misma causa.

Las puertas lógicas trabajan sobre los datos boleanos, digamos que son ellas las que hacen:
stream(Hex1) Hex1()
que en realidad se trata de un direccionamiento de posición, es como hacer en asm de x86:

[es aproximado] */si tienes windows puedes probar esto en debug.exe, ejecutar debug.exe/*

worda=[numerohex]
mov worda,0100h

Lo cual situaría el valor numerohex a la posición 0100h de la memoria. Como hex es una única cifra
en hexadecimal pues ocupará una única casilla hexadecimal a partir de 0100h, es decir, un solo nibble:

creamos MEM(ffffh)  -que representa la memoria de nuestro programa en nivel bajo. es una memoria, por
lo tanto es una matriz boleana de dimensión ffffh es una matriz enorme,
así que tenemos memoria de sobra. creamos entrada que es el número
hexadecimal que vamos a almacenar.

stream (entrada()) a entradab()  -pasamos a boleano a través de un stream a toda la memoria.
trim (entradab()) -eliminamos todos los caracteres que nos sobran.
MEM(0100h)=entradab() -y guardamos el dato en la posición 0100h, como hicímos en assembler.

introducción al tutorial -PROGRAMACIÓN INFORMÁTICA GENERAL-

introduccion
____________________________________________________

En este tutorial se va a tratar el tema de el manejo de la información en sistemas informáticos, no solo las computadoras personales comunes, sino de un modo genérico para diferentes sistemas. Además el enfoque tratará de alejarse de la línea típica de los tutoriales, dirigiendo la resolución de problemas a explicaciones matemático-lógicas de fácil entendimiento si se siguen paso a paso, pero que pueden resultar "espesas" si no se digiere poco a poco. No es necesario mucho conocimiento matemático, ya que las expresiones vendrán dadas en un lenguaje flexible y accesible. Si es aconsejable algo de familiarización o bien con electrónica o bien con informática, aunque no es obligatorio, ya que todo se explica poco a poco. Si no entiendes algo, espera, vuelve a leerlo, síguelo paso por paso y al final cobrará sentido. Si pasas por alto un paso y sigues leyendo quizás te pierdas y no puedas retomar el hilo, así que paciencia.

Incluso queriendo facilitar la información con expresiones en "castellano plano" debido a que se requiere cierta precisión se utilizarán ciertos símbolos, así como los aritméticos +, -, *, /, %(o mod que es el resto de una división) y símbolos de referencia:

Ésto es lo que debes de saber para entender el primer capitulo, ya que utiliza un lenguaje que queda entre el pseudocódigo y el algebráico, relaccionando algoritmo con matemática y electrónica cuando sea posible. Se aconseja acudir a leer primero.txt en caso de dudas sobre el propio lenguaje utilizado.

tipos de valores que se utilizarán:

(si no entiendes que significa alguno de éstos tranquilo, sigue leyendo que se van explicando paso a paso, vuelve a esta tabla si lo necesitas)

null:   null significa nada, vacío, 0, ningun carácter, apagado o no, segun el caso.

numero común:  pues eso, 1, 500, 5.500. Significan su valor en decimal, pero ya explicaremos que en realidad no es decimal, sino binario.

numero hexadecimal: lo indicaré con una h al final, como se suele hacer. 3dbh, 43h,10f0h.

numero binario: numero en notación binaria. 100101, 10 ,110110.

interrupcion boleana: esta significa o si o no, y se expresa normalmente en true o false, o 1 y 0.(true, false, 0, 1) Solo puede tener un carácter y llama interruptor.

texto, char : trataremos valores de texto, por un lado char indica un sólo carácter ,y texto es una cadena de char, uno detrás de otro, el valor va entre comillas.

valores dinámicos: son como las variables comúnes de programación, o las expresiones matemáticas simbólicas, significan un valor que puede cambiar(x=3,r2+r3=v3) para expresar números. Normalmente se declararán con un tipo (vamos, que dire: tengo r2 que es un número entero, o tengo Ck que es una interrupcion).

matriz dimensional: En ocasiones requeriremos manejar colecciones muy grandes de datos de manera similar entre sí, para ello utilizaremos una expresión bien conocida en el mundo de la programación, una matriz. una matriz representa una colección de datos del mismo tipo. Una matriz se expresa por un identificador, similar al de las variables y un número entre paréntesis, al que llamaremos puntero. Si no existe puntero, pero si paréntesis entendemos que nos referimos a todo el grupo de valores en la colección. Para indicar el tamaño de la dimensión de la matriz se puede hacer en el parentesis cuando se declara. Es decir:

creamos una matriz de números Test(100)  - o sea, una matriz que se llama Test y puede contener de 0 a 100 números.

Test() se refiere a toda la colección de elementos.
Test(0) se refiere al primer elemento de la matriz, ya que el cero cuenta.
Test   se refiere a el tipo de elemento que se contiene, se pueden hacer cosas como: (por cada Test en Test() Ck=Ck++), lo que contaría el número de entradas Test.
Test(+)significa la suma total de todos los valores individuales, se puede hacer con cualquier expresión. (String=char(&), Test=Nums(-)). el orden de las operaciones
sigue el incremento de puntero.

Un par de funciones que solo usaremos con colecciones es Split y trim. Ya se explicará que es una función en adelante.

Split(variable) separa cada unidad o cifra que forma la variable y la guarda en Variable() que es una colección del mismo tipo, a menos que se especifique otro.
trim(matriz()) elimina todas las casillas "nulas"en la matriz. entendemos como nulo el 0 en todos los modos, excepto en texto o char, que será "" o null.

por ejemplo:


aritméticos:

+ y - ya los conoces, para indicar +1, en ocasiones se podrá usar += (1+3=4 ,1+=2, 2-=1)
* significa por (X) se usa comúnmente (2*6=12)
/ es el simbolo de división (4/2=2)
% o mod(num,num) es módulo y se usa para hayar el resto de la división (5%2=1, mod(7,3)=1)
^ o ** es elevado a, se usa comúnmente (2^2=8 ,2**2=8)
= el de siempre, en ocasiones es sentencia y en ocasiones condición (si x+3=4, y=3, 1+2=3)
& es para concatenar, es decir, no suma, sino que pone un número detras de otro. Éste tambien funciona con texto y char (10 & 4=104 ,con & cat=concat)

Con esto puedes empezar el capitulo uno.