Autor Tema: Modelos estándar de N en la computadora

0 Usuarios y 1 Visitante están viendo este tema.

01 Diciembre, 2014, 12:03 pm
Respuesta #20

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,796
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
Citar
En principio también se podría hacer un programa para operar aritméticamente con caracteres char;

Eso no anda bien, porque hay límites desde el mismo lenguaje.
Para indicar un vector de elementos de tipo char, hay que reservar memoria cada vez,
intentando agrandar el tamaño del vector, así:


char *number; /* Declaración de puntero a dirección de memoria RAM conteniendo char */
number = malloc(2); /* Reserva 2 bytes: 1 byte para un dígito y 1 byte para marca de final de string */

number[1] = '\0'; /* Marca de fin de string (código ASCII 0) */
number[0] = '0';  /* El único dígito disponible lo pongo a '0' (código ASCII 48) */

/* Aquí number está representando el número natural intuitivo 0 */
.....

/* Ahora intento que number represente un número con 230 dígitos. */
/* Antes de lograrlo, necesito reservar 230 bytes para los dígitos, y 1 más para el final de string. */
/* Se usa la función realloc() para reservar memoria suficiente, y sin borrar el contenido previo: */

number = realloc(number, 231);
number[230] = '\0';


Ahora bien, fíjate que en la sentencia que usa realloc(), el segundo parámetro tiene que ser un número entero, pero no cualquier número, sino uno de tipo size_t.

El tipo de datos size_t tiene un valor máximo posible.
Más aún, su valor máximo está acotado por el máximo valor admitido por el tipo de datos uintmax_t.
En los sistemas actuales, este valor anda más o menos por \( 2^{64}-1 \).

O sea que la cantidad de dígitos de un array de char podría ser a lo sumo \( 2^{64}-1 \).
No hay (o no se me ocurre) manera en que pueda agregarle dígitos de uno en uno, con realloc().
Tendría que poder agregarle bytes "detrás", y aunque se me ocurren algunos modos extravantes de hacerlo con la familia de funciones xx_alloc(), es muy probable que sean malas prácticas de programación (o sea, dando resultados no previsibles).

En resumidas cuentas, el lenguaje presenta limitaciones al tamaño de un vector de datos de un tipo dado.

----------------

En cambio, al usar una lista enlazada, se ha de reservar memoria cada vez para un único dígito (y el enlace link), lo cual es más engorroso, pero desde un punto de vista teórico es correcto, porque el lenguaje no presenta limitación alguna en cuanto a la cantidad de veces que esto puede hacerse.

Así que el número de dígitos así expuesto es ilimitado.
La sintaxis y especificaciones del lenguaje no imponen limitaciones, y por lo tanto me permite representar cualquier número natural, por grande que sea.

Esta posibilidad es abstracta, o sea que no difiere del todo del carácter mental que tienen los naturales intuitivos.
Siguen siendo un modelo de los números naturales, incluso a nivel abstracto, mental.

Si tenemos una buena máquina, es posible representar el número natural que queramos, por grande que sea.

Citar
En cualquiera de los casos, la memoria se va a gastar antes o después, tanto metiendo los datos directamente en las direcciones de memoria o por medio de comandos de más alto nivel (matrices o lo que sea).   

 Entonces, la cuestión es si eso sería un modelo de los números naturales o un modelo de cómo nosotros usamos los números naturales:

Claro que se va a gastar.
Pero eso no es una imposición de la sintaxis del lenguaje.
Si estás obligado a usar size_t, entonces el lenguaje mismo te acota la cantidad de dígitos a un número finito.
En cambio, mediante la técnica de lista enlazada, el lenguaje no impone ninguna restricción,
y en cambio las limitaciones de memoria dependen de "la máquina" o "sistema" en que el programa se compila y corre.

El estándar que define el lenguaje C es muy general respecto el tipo de "máquina" en que el lenguaje C va a correr. No especifica demasiados detalles, dejando la puerta abierta a una gran variedad de posibilidades.
Esto se llama: la máquina abstracta de C.

O sea que, en realidad, al escribir un programa, estamos escribiéndolo para que corra en esa "máquina abstracta", y no en una máquina real.

Luego, cada compilador hace sus elecciones acorde a la máquina real en que se va a ejecutar el programa.

Pero, como bien ha dicho Carlos, un programa es algo mental, abstracto.
Yo podría "correr" el programa en mi cabeza, haciendo una simulación con la imaginación.
Ahí no tendría problemas de memoria RAM (eso creo, no lo sé).
O bien, podría considerar que todos los seres vivos del Universo juntamos "RAM" para representar dígitos, y así vamos representando números cada vez más grande.

La posibilidad de representar un número en la realidad depende de la imaginación...
y también de la cantidad de materia del Universo, útil para representar información.

Pero esto no interesa demasiado, porque, como vos decís:

Citar
Yo, lo que sí veo, es que supone “enseñarle” al ordenador a operar de forma más parecida a un humano;

Eso mismo. Lo que hacemos es definir una estructura que, en abstracto, "permite" representar cualquier número natural, y luego sobre esa estructura definimos las operaciones y relaciones típicas de los naturales.

"Eso" da un sistema que funciona/opera/trabaja igual que los naturales, y podemos "extraer conclusiones sobre ellos".
Las conclusiones, como insiste Ivorra por ahí, son intuitivas.
El programa no podrá extraer todas las conclusiones sobre sus números.

No obstante, las conclusiones que obtendremos sobre estas entidades serán las mismas que las que obtendremos sobre los números naturales. Son sistemas isomorfos.

Citar
Sin embargo, cuando un programa de alto nivel se compila para que opere en su código, quizá no hace otra cosa que operar con una lógica humana, porque por muy código máquina que sea, ese código lo hemos inventado los humanos, no las máquinas.

Pienso que está mal razonar así.
Tu idea de usar "strings" para representar dígitos es una "idea humana", pero te he mostrado que no sirve, porque el lenguaje tiene limitaciones en su definición, o sea, hay razones técnicas que hacen que C, inventado por humanos, no sea capaz de representar números arbitrarios mediante meras strings.

En cuanto a los lenguajes de alto nivel, no puedo decir nada, porque no sé cómo están definidos (porque no lo he estudiado), ni cómo están implementados.
Por ejemplo, en Python se supone que hay un tipo de datos "integer" que representaría cualquier número natural. ¿Es cierto esto?
Si se usa la técnica de un array, ya sea de caracteres o de enteros-de-máquina, lo que fuere, y si el código no está escrito con el suficiente cuidado, puede que haya un máximo de dígitos, y entonces no serían "enteros cualesquiera" los que Python permite.

En realidad esto no lo sé. Hace un tiempo estuve buscando información sobre esto, y no encontré nada concreto. Me pareció que Python, en la práctica, tiene (o tenía) limitaciones en el número de dígitos (quizás esto de los \( 2^{64} \) dígitos aplique a Python), pero es posible que me equivoque.
Después de todo, he mostrado que es posible definir una estructura de datos (recursiva) que permite representar cualquier entero.
Así que Python puede estar bien, aunque para saberlo debiera analizar el código conque está escrito.

Citar
Citar
(No me hagan discutir diciendo cosas como que "¿qué pasa si estamos en un Universo en que vemos/intuimos los naturales creyendo que son los de verdad, pero un demonio desde afuera del Universo considera que los naturales que vemos son no-estándar?").

Pero es que ahí es donde yo creo que está el quid de la cuestión, tarde o temprano vamos a llegar a discutir sobre eso: ¿Es objetivo el concepto de “numerable” o depende del “observador” que va llevando la cuenta? ¿Cuáles son los naturales estándar o no estándar, de qué o de quién depende eso? ¿Puede existir un “demonio” que use una base numérica cuya “cantidad” de símbolos, desde nuestro punto de vista, sea infinita? Si la respuesta la consideramos afirmativa ¿deberíamos considerarlo relevante o hacemos caso omiso del demonio ese? Si hacemos caso del demonio o del marciano o lo que sea, por lo menos podríamos suponer o dar por bueno que tanto él como nosotros usamos alguna base numérica y, con ella, un método para hacer sumas y multiplicaciones.
 Y a partir de aquí, antes de otras cosas, lo que tenemos que hacer es ponernos de acuerdo sobre si siempre que alguien usa una base simbólica, y unas reglas concretadas por alguien, está usando números que podemos llamar naturales.

Si bien todo eso es posible, especular sobre seres extraños y demonios va más allá de lo que podemos comprobar empíricamente.
Es una especulación sin demasiado sentido, porque no hay hechos en los que apoyarse para discutir.
Por eso no creo que me vaya a ir por ahí.

01 Diciembre, 2014, 12:43 pm
Respuesta #21

feriva

  • $$\Large \color{#a53f54}\pi\,\pi\,\pi\,\pi\,\pi\,\pi\,\pi$$
  • Mensajes: 11,991
  • País: es
  • Karma: +1/-0
  • Sexo: Masculino


Citar
Por ejemplo, en Python se supone que hay un tipo de datos "integer" que representaría cualquier número natural. ¿Es cierto esto?
 
No que yo sepa, creo que los datos integer, por lo que he mirado, son simplemente los que se definen como “int”, y tienen un límite igual que los float, si intentas trabajar con un número muy grande te dice que “overflow”. 

Citar
Si bien todo eso es posible, especular sobre seres extraños y demonios va más allá de lo que podemos comprobar empíricamente.
Es una especulación sin demasiado sentido, porque no hay hechos en los que apoyarse para discutir.
Por eso no creo que me vaya a ir por ahí.

Es que yo no estaba pensando realmente en seres de fábula, sino en virus o en seres humanos muy lejos de mí a los que vería como hormigas o no vería; y en más cosas.
 Hay umbrales en todo, y la consideración de que algo es infinito o finito (o estándar o no estándar) quizá pueda ser como un umbral mental; en ese caso, el concepto puede ser aún menos absoluto de lo que pensamos. Voy al grano, ¿existen números que no sean básicamente naturales? La pregunta no se puede responder sin más, quizá dependa del un acuerdo entre “observadores” (o pensadores). Y cuando hablamos de capacidad de la RAM, lo mismo, estamos hablando de umbrales.  Por ahí es un poco por dónde quería ir.

01 Diciembre, 2014, 01:45 pm
Respuesta #22

feriva

  • $$\Large \color{#a53f54}\pi\,\pi\,\pi\,\pi\,\pi\,\pi\,\pi$$
  • Mensajes: 11,991
  • País: es
  • Karma: +1/-0
  • Sexo: Masculino
Le estoy dando vueltas a un cosa.
Hacer un programa que genere infinitamente un mismo símbolo repetido es muy simple; basta un bucle infinito y un “print símbolo”. Incluso se pueden imprimir en pantalla, aunque ésta hace trampa borrando los símbolos que va mostrando cuando éstos ya no caben al aparecer más símbolos nuevos.

Uno, subjetivamente, puede entender que ahí se van representando los números naturales  imaginando unos paréntesis

(((0)0)0)...

Pero si uno quiere que sea el ordenador el que muestre esta distinción es cuando viene el problema de memoria; o bien por especificaciones del lenguaje o bien porque no hay más sitio. En cualquiera de los casos es un problema de almacenaje.

Y dicho esto la cuestión es: si yo doy una cantidad indefinida de  golpecitos en una mesa sin contar los golpecitos, ¿puedo llamar a eso números naturales estándar? Estamos en el caso del bucle que repite un mismo símbolo sin gastar memoria, porque va borrando el “recuerdo” de esos símbolos cuando ya no caben más en la pantalla. Luego la idea de números naturales (al menos de los naturales estándar) quizá no es independiente del almacenaje o, si se quiere decir de otra forma, del “recuerdo”.  Pero en matemáticas puras no sé si hay algún teorema o algún axioma o algo que considere  ese “almacenaje” o “recuerdo”. Visto de otra forma, si yo escribo el número, qué sé yo, 150, sólo tiene sentido si de alguna manera existen individualmente el 1 el 5 y el 0, y aún es más, sólo tiene sentido si están “guardados” (no sé cómo, pero guardados de alguna manera abstracta) todos los números naturales hasta 150.

 En fin, hoy, y muy excepcionalmente, tengo que salir de casa para ir a comer fuera, pero sospecho que cuando vuelva, seguramente, me voy a poner a pensar en programar algo (algo que a buen seguro será imposible de programar).

Saludos. 

14 Diciembre, 2014, 11:40 pm
Respuesta #23

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,796
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
Lo de dar "golpecitos" en la mesa no sería un modelo de números naturales, porque no es cierto que una persona sea capaz de dar N golpecitos, donde N es cualquier número natural, tan grande como a uno se le ocurra.

Si N es muy grande, la persona habrá muerto antes de dar todos esos golpecitos.
Si se descubre la fórmula de la inmortalidad, habrá de todos modos un momento en que la mesa dejará de existir, o el planeta en que ésta se apoya, o bien habrá un desacople de los átomos del Universo que hará desintegrar la materia ordinaria, y no podrán darse golpecitos.

Las observaciones que has hecho acerca de la "falta de memoria" son y no son pertinentes.

Hay dos posibles problemas:

(1) O bien el lenguaje de programación utilizado es incapaz de expresar estructuras lo bastante versátiles que permitan generar un cálculo análogo al de los números naturales (incluyendo: el operador siguiente, el buen orden de N, las operaciones de suma, resta, producto, cociente, resto, potencia, raíces, logaritmos, y alguna que otra fruslería),

(2) O bien el lenguaje de programación es lo bastante expresivo para hablar de algo equivalente a los naturales intuitivos, pero que se encuentren limitaciones prácticas cuando el programa finalmente corre.

El caso (1) se da obviamente con tipos de datos como "int", que permite expresar valores enteros entre -32768 y +32767.
Es una limitación del lenguaje, y no permite expresar valores fuera de ese rango.

Entonces cabe la pregunta de si, jugando con las estructuras de datos, sea posible generar algo que sí permita obtener una estructura de "naturales".

El problema aquí no es la falta de memoria.
El problema, dijo Arjona, es tu sintaxis.

La primer idea que a uno se le ocurre es usar cadenas de caracteres para representar los dígitos.
En Pascal, el máximo tamaño que puede tener una cadena de caracteres es 255.
O sea que si usáramos caracteres para representar los dígitos de un número natural,
y los números naturales se representasen con cadenas,
entonces sólo podríamos hablar de naturales menores que \( 10^{255} \).

En C, aparentemente, no existe esta restricción, porque una cadena de caracteres se programa
como un objeto en memoria formado por una cantidad de caracteres de tamaño arbitrario, y cuya longitud está determinada apenas por un marcador de "fin de cadena".

¿Acaso es la falta de memoria el impedimento para representar números muy grandes?
No.
De nuevo el problema es la mera sintaxis del lenguaje.

Como ya expliqué antes, para especificar cualquier cadena de caracteres en C,
antes hay que reservar memoria suficiente.
Supongamos que tenemos un sistema con memoria infinita.
Aún en este caso maravilloso e ideal, no sería posible tener cadenas de caracteres de tamaño grande cualquiera.
El problema es que, cada vez que uno quiere reservar una determinada cantidad N de bytes en la memoria,
necesariamente tiene que especificarlo con un valor numérico, diciendo cuántos bytes queremos reservar.
Y este valor numérico tiene que ser compatible con size_t.
Y size_t es un tipo de datos aritmético de C, al igual que lo son el int, el char, el float, y otros.
Como consecuencia, este tipo de datos tiene, al menos en C, un máximo valor posible.

Ese máximo valor posible será, tristemente, la máxima longitud que podrá tener una string en memoria.

Este máximo valor no importa cuál es.
Lo único que importa es que: es finito.

En realidad hay algunos trucos para tener tamaños más grandes.
Pero estos trucos (por ejemplo usar arrays multidimensionales), de nuevo dan una cantidad finita de dígitos.

Lo que nos queda entonces es usar una estructura dinámica de datos,
que por suerte en C existe.
Hay que recurrir a la técnica de listas enlazadas.
Aquí, se define una estructura de tamaño fijo, que se repite tantas veces como uno necesite,
y según la necesidad.
Cada repetición está "enlazada" con la siguiente, lo cual permite al programador llevar el control de los dígitos del "mismo número".

Ahora bien.
Esto sigue estando del lado "sintáctico", y quiere decir que es una cosa que define el lenguaje.
Al correr un programa, es posible generar números naturales tan grandes como queramos.
Pero ahora las limitaciones están en la máquina o sistema que corremos el programa, que nunca permitirá llegar a representar los infinitos naturales.

Por todo esto es que, a fin de cuentas, el "artefacto" de las listas enlazadas de dígitos siguen siendo una abstracción.
O sea que son, todavía, una construcción mental, más complicada que la mera intuición de los números naturales.

La ganancia está en que hemos trasladado el "trabajo intuitivo" a la máquina.
La "complicación" de la estructura proviene de la mecanización de la misma fuera de la mente humana.

La "estructura" de lista enlazada de dígitos es algo que "permite" la generación, en máquina, de un número natural cualquiera.
Y si la estructura está bien hecha, se pueden hacer operaciones aritméticas, o comparaciones según el orden natural de los números.

-------------

¿Qué es lo que se ha obtenido?
¿Un conjunto abstracto de números naturales?
Y sí, pero "potencialmente" el programa es capaz de generar cualquier número natural.
Y este programa es "real", es decir, es una secuencia finita de pulsos magnéticos guardados en un disco (o sea, información computacional), que en una computadora real es capaz de generar tantos dígitos como uno quiera, siempre que la máquina lo permita.
Eso es un programa, a fin de cuentas, una información almacenada en un dispositivo magnético, que "hace algo" en interacción con una máquina adecuada.
El "software" nuestro no tendría limitaciones a la hora de crear listas enlazadas muy grandes.

Y no es cierto que la máquina pueda tener una limitación práctica.
A ver. Es verdad que una computadora viene con una cantidad finita de RAM.
Pero aunque hoy en día no existe, me parece bastante factible realizar un protocolo de comunicación de internet que permita interconectar tantas computadoras como se quiera (o sea, un I.P.V.\( \infty \), en vez del actual I.P.V.6, o el viejo I.P.V.4).
En ese caso, cuando alguien hipotéticamente necesite más memoria RAM para almacenar un número muy grande, puede solicitar "RAM en la nube" prestada, para almacenar más dígitos.
Esta tarea tiene que gestionarla, o bien el sistema operativo (Windows, Linux), o bien el navegador.

En cualquier caso, me parece tecnológicamente factible, teniendo en cuenta lo que hoy en día YA existe.

Así que, no sólo tendríamos una estructura potencialmente infinita para el software,
sino también la "arquitectura del hardware" ahora, con un protocolo adecuado de Internet,
tendría un sistema con soporte potencialmente infinito.

Aunque esto es más "hard" que "soft", sigue siendo "soft", porque en realidad lo único que estoy haciendo acá es tener en cuenta una limitación intermedia: entre el programa hecho en C y compilado, y la computadora, hay un sistema en el medio que puede ser limitado en sus capacidades. O sea, el sistema operativo y los protocolos de internet, que son software, pueden estar mal diseñados, e impedir, por su diseño, que se pueda acceder potencialmente a tamaños arbitrarios de memoria RAM que haya "por ahí".

Pero una vez solucionado este aspecto más intrincado de arquitectura del sistema,
diseñado para aceptar cualquier computadora adicional que se le intente adosar,
viene el impedimento físico.
Lo único que tiene que hacer el sistema entonces es informar cuando se queda sin suficiente RAM, esperar a que alguien incorpore una nueva máquina (o crear un sistema automático que cree una nueva máquina y la añada, o sea, "hacer un hijo" y sumarlo a la red de máquinas del sistema), y así expresar ese bendito número natural tan grande que se nos escapa.

Estas máquinas más o menos ya existen, y se llaman "seres vivos".

Como sea, hay límites en la cantidad de RAM "física" que podamos adquirir por cualquier método,
y entonces el sueño se acaba tarde o temprano.
Pero la "potencialidad" de agregar siempre una máquina más a la red, es algo que permanece, al menos durante la duración de la materia ordinaria.
Más allá de ese tiempo, no vamos a existir, así que tampoco importa demasiado.

.................

Pero entonces, ¿qué se ha logrado?
Simplemente automatizar lo mismo que ya teníamos en la mente humana.
Esto es, el potencial de generar cualquier número natural, y sus operaciones con ellos.

Ahora bien.
Lo que rescato de tus comentarios (feriva), es que has puesto de relevancia que la necesidad de tener "bastante memoria" tiene que ver con el concepto de número natural.

Si yo doy golpecitos en la mesa, pero nada ni nadie los "recuerda", ni tan siquiera los "asocia", entonces no hay modo de asignarles un número.
Lo mismo si los generamos en la pantalla.
Si no hay alguien/algo que asocie esos dígitos de alguna manera, que los "recuerde" en alguna forma, o que al menos recuerde o asevere lo que ha "ocurrido", no hay manera de asociar un número a "eso.
Dado que la memoria es algo frágil, me entran dudas de cómo tomarme esto epistemológicamente hablando.

Por otra parte, lo que uno puede apreciar al "bajar" los naturales intuitivos a la computadora,
y toparse con dificultades, es el grado de complejidad que hay escondido detrás de esa intuición aparentemente tan sencilla.

Si yo "materializo" los naturales intuitivos de alguna forma, y eso me trae dificultades de cierto tipo, es que esas dificultades dan claves sobre la naturaleza intrínseca de estos objetos intuitivos que estoy considerando.
En particular, la participación de "la memoria" en algún grado, hace falta para que podamos siquiera decir algo sobre los números, o algunos de ellos.

Hay una dificultad creciente de trabajar con números a medida que son cada vez más grandes.
Aunque a veces podemos hablar de ciertos números grandes sin dificultad (por ejemplo, del \( 10^{10^{10}} \)),
en general cualquier número bastante grande traerá complicaciones de "tamaño" y "memoria" para poder representarlo.

Mi tesis aquí es que, entonces, no es equivalente la "intuición" del número 2, que la del número \( 222222^{222222222} \).
La intuición de lo más complejo es más ardua que la intuición de lo más simple.
O sea que en realidad no habría, digo yo, "una sola" intuición metamatemática,
sino una escala graduada de intuiciones.

Y esto es una de las cosas que hace que, de nuevo, me vuelva a cuestionar la fiabilidad o el sentido último de las intuiciones metamatemáticas.
Me gustaría una herramienta más "uniforme".

----------------------------

De cualquier manera, la construcción que he sugerido de listas enlazadas en C para representar naturales intuitivos, es, y lo digo para resumir un poco, potencialmente infinita y bastante automática.
La automatización completa depende de otros factores, que me parecen totalmente plausibles en la práctica.

La automatización en la máquina de los números naturales, fuera de la mente humana, es posible.

Hay otras cosas más dañinas que uno podría preguntarse, pero mejor otro día...