¿Es posible iterar a través de todos los números reales en [a, b] en cualquier lenguaje de programación? ¿Se acerca algo?

Para dar sentido a esta pregunta, permítanme agregar una palabra – “representable” – antes de “números reales”. Dado que los números reales están representados por la mayoría de los lenguajes de programación con cierta precisión, solo hay un conjunto finito de números reales representables entre números reales finitos [math] a [/ math] y [math] b [/ math]. El formato de representación generalmente está determinado por el hardware (la CPU), que hoy sigue predominantemente el estándar de coma flotante IEEE (IEEE 754). Los dos tipos de datos más comunes son el float 32 bits y el double 64 bits. Entonces, dadas dos variables float (o dos variables double ), ¿cómo iteramos entre todos los valores representables intermedios?

Michael Sherman señala que

C99 y C ++ 11 tienen funciones nextafter () y nexttoward () que devuelven el “siguiente valor representable” para los tipos de punto flotante. nextafter – Referencia de C ++

Si sabe algo sobre el estándar IEEE 754, puede profundizar en los bits (o al menos comprender cómo funcionan esas dos funciones). Ahorraré los detalles sangrientos de cómo el exponente y el significado se almacenan en IEEE 754, pero lo que importa es que la conversión de bits de los números de punto flotante en un entero con signo (en la representación de magnitud con signo) conserva el orden . En otras palabras, si toma los 32 (o 64) bits sin procesar del número de punto flotante y lo mira como si fuera un entero con signo (los tipos int o long long int respectivamente), entonces la relación entre los dos números se conserva para números positivos y para números negativos (se requiere un poco más de trabajo para manejar a <0 <b). Tenga en cuenta que la conversión de bits es muy diferente del redondeo y no corresponde a ninguna operación matemática (como el redondeo). Si observa lo que hace la conversión de bits a los números reales, el resultado parece arbitrario.

De todos modos, la propiedad de preservación del orden implica que cualquier número de punto flotante entre [math] a [/ math] y [math] b [/ math] se mapea en un entero con signo entre las variantes enteras de esos números. ¿Cómo nos ayuda el mapeo a enteros aquí? Ayuda porque para los enteros tenemos la operación “siguiente”, también conocida como i++ o i = i + 1 . Entonces, todo lo que necesitamos hacer es

  • bit-cast a, b a enteros con signo de tamaño apropiado
  • incremente a hasta que llegue a b
  • Bit-Cast una copia de cada número intermedio de vuelta al punto flotante

Para lograr la conversión de bits en el lenguaje C,

  • tomar la dirección de la variable de punto flotante
  • convierte el puntero a flotante resultante en un puntero a int
  • desreferenciar el puntero resultante y usar el valor

En C ++, tenemos que tener más cuidado con los moldes. Cuando siga los mismos pasos, use reinterpret_cast para la conversión del puntero.

Para manejar el caso general (incluyendo a <0 <b), verifique el bit más significativo: si es 0, hágalo 1; si 1, niega (voltea) todos los bits. Lo creas o no, tuve que escribir este código en el trabajo (para una aplicación práctica, diferente de esta pregunta).

Antes de escribir el código real, tenga en cuenta que los números de punto flotante se imprimen con una precisión bastante pequeña de forma predeterminada, por lo que cuando comience a iterar, puede parecer que el número no está cambiando. A menos que solicite específicamente imprimir esos números con la máxima precisión. En C / C ++, esto se puede lograr utilizando el formato printf apropiado para float o double . Si usa la salida de flujo en C ++, necesitará el setprecision() E / S setprecision setprecision() .

Espero que esto ayude.

Georg Cantor demostró que los números reales ni siquiera se pueden enumerar . Eso significa que es imposible crear una lista ordenada de los números reales en cualquier intervalo. (Cantor comenzó su hermosa prueba asumiendo que tenías una lista de todos los números reales. Luego explicó cómo construir un número que no está en la lista, demostrando que no puede existir esa lista). Si no puedes crear una lista ordenada de números reales, no puede decidir qué número viene después, por lo que ciertamente no puede iterar sobre ellos.

Sin embargo, surge otro problema al representar incluso un solo número real. Supongamos, por ejemplo, que su intervalo es [matemáticas] [\ pi, \ pi + 1] [/ matemáticas]. El primer número en el intervalo, [math] \ pi [/ math], es computable, pero tiene un número infinito de dígitos. ¡Tendría que esperar para siempre (literalmente) solo para imprimir el primer número en el intervalo! Solo sabemos los primeros trillones de dígitos de [math] \ pi [/ math], después de todo …

Incluso si el primer número en su intervalo resultó ser racional y podría calcularse en una cantidad de tiempo finita, hay un número infinito de números irracionales entre dos números racionales, por lo que se encuentra con el mismo problema.

Afortunadamente, para cálculos prácticos, a menudo puede obtener excelentes resultados utilizando números representables por máquina integrados en un lenguaje de programación: flotantes y enteros de 64 bits.

Respuesta corta: no.

Detalles:
Para poder iterar a través de los elementos de un conjunto, necesita alguna forma de saber cómo encontrar el siguiente elemento de tal manera que sepa que los examinará a todos.

Aquí hay un ejemplo simple: supongamos que quiero iterar a través de los elementos de {‘a’, ‘b’, ‘c’}. Como hay tres de ellos (puedo contarlos), puedo inventar una función sin pérdida de generalidad de los números naturales (0,1,2 …) a estos elementos:
1 -> ‘a’
2 -> ‘b’
3 -> ‘c’
(o cualquier permutación de estos)

y luego iterando a través de los números 1,2,3 sé dos cosas:
(1) Examinaré todos los elementos del conjunto
(2) Tengo una manera de examinar todos los elementos del conjunto.

Los conjuntos no definidos se dividen en dos categorías:
(a) del tipo en el que puedo escribir una función de los números naturales para enumerarlos a todos como vimos anteriormente (estos se llaman conjuntos contables )
(b) el tipo donde no puedo (conjuntos incontables )

Los números reales son incontables (vea el argumento diagonal de Cantor para un ejemplo).

En un sentido práctico, podemos tomar dos números reales y preguntar si son iguales o si uno es mayor que otro. Con números naturales (y conjuntos finitos) podemos hacer algo más: podemos encontrar el siguiente elemento más importante.

Es precisamente porque no hay un “próximo número real más grande” que no se puede iterar a través de los reales.

Esto significa que incluso si imaginara trabajar con un tipo especial de computadora que podría trabajar directamente con números reales (o cualquier intervalo de ellos), esta computadora aún no podría enumerar elementos del intervalo [a, b] porque los números reales no son No se puede contar y no tiene una función de elemento siguiente .

Solo si afloja la definición de número real o la definición de iterar. Igor Markov ya cubrió el primero, que probablemente esté más cerca de lo que querías decir. Solo diré un par de palabras sobre esto último.

Dada la definición normal de iteración como repetición explícita, claramente no es posible iterar sobre todos los números reales en un rango arbitrario, ya que (como se señala en las otras respuestas) hay infinitos números reales en cualquier intervalo [a, b] suponiendo que a

Sin embargo, algunos lenguajes de programación le permitirán aplicar la cuantificación universal (en lugar de la iteración) a un intervalo real, para afirmar declaraciones que sean verdaderas en todo (sin verificar cada valor individualmente). Un ejemplo es el asistente de prueba Coq.

Matemáticamente hablando, los números reales no existen en los sistemas informáticos (aparte del subconjunto finito). Todos los sistemas informáticos funcionan con datos discretos solo por naturaleza y los números reales son continuos. Todo lo que sea discreto, ordenado y computable (y la representación de números reales en los sistemas informáticos generalmente lo es) se puede repetir en cualquier lenguaje completo de Turing (y la mayoría de los lenguajes de programación son completos de Turing).

Dado que los números reales son innumerables, ni siquiera es posible en teoría, y mucho menos por una computadora. Incluso si una computadora lo intentara, siempre estaría limitada por la precisión de coma flotante de su sistema de números, por lo que prácticamente ni siquiera está cerca.

Eso sería un número infinito de iteraciones.

Para iterar en un conjunto, necesitaría que fuera contable (gracias @Paul Bristol por su aclaración) y tener un tamaño finito dentro de los límites de sus recursos.

El conjunto de números reales entre ayb tiene infinitos elementos.

El tipo de datos que usa para representar un número real puede o no tener una precisión limitada, por lo que en el primer caso podría usar la precisión mínima como el tamaño del paso al iterar, pero enfrentaría el problema de los errores de redondeo. Otras publicaciones han sugerido enfoques razonables para ciertas representaciones de números reales.

Ciertamente lo es!

Dependiendo del caso, por supuesto.

  1. a : No, por los motivos indicados en las otras respuestas.
  2. [matemáticas] a = b [/ matemáticas]: ¡Por supuesto, solo una iteración! 😉
  3. [matemática] a> b [/ matemática]: considere la definición de [matemática] [a, b] [/ matemática]: [matemática] [a, b] = \ {x \ in \ mathbf {R}: x> = a \ ^ \ x <= b \} [/ math] = el conjunto vacío, ya que a> b. Entonces, todo lo que se necesita es cero iteraciones. 😉

Teóricamente, no puede contar todos los números reales en ningún intervalo no vacío. Probar esto está fuera de contexto aquí, aunque puede encontrar una prueba aquí (Contando los números reales)

Entonces no. No hay y nunca habrá uno.

Esta respuesta resultó ser una lectura difícil. Entonces, lee hasta el final. ¡Cada palabra cuenta! Comencé con SÍ, pero es un “SÍ” condicional.

Yo diré que sí.

¡Puedes hacerlo con cualquier idioma sabiendo cómo realizar la integración!

[matemáticas] \ displaystyle \ int_a ^ bx [/ matemáticas]

En realidad es como:

[matemáticas] \ displaystyle \ sum_a ^ bx [/ matemáticas]

pero en lugar de sumar enteros, sumas sobre reales.

También puede calcular el promedio de su rango. Sería como si sumaras cada real y dividido por el número de números reales en tu rango.

Para las personas que desean un “for” o “while” para demostrar que es una iteración, mire APL: “/ + A” sumará todos los elementos en la lista A.

Yo llamaría a eso “iteración indirecta”.

Curiosamente, el “número” de números reales en [a, b] (o la cardinalidad) es el mismo que en (-inf, + inf). Entonces no, no es posible iterar en todos ellos. Ese tipo de conceptos solo puede existir en nuestras mentes, no en la realidad.