math - numeros - Una pequeña distracción en la precisión del punto flotante(im), parte 1
punto flotante ieee 754 ejemplos (10)
La mayoría de los matemáticos están de acuerdo en que:
e πi + 1 = 0
Sin embargo, la mayoría de las implementaciones de punto flotante no están de acuerdo. ¿Qué tan bien podemos resolver esta disputa?
Tengo muchas ganas de escuchar sobre diferentes lenguajes e implementaciones, y varios métodos para hacer que el resultado sea lo más cercano posible a cero. ¡Ser creativo!
De hecho, ¿cómo representa uno i (o j para los ingenieros) en un lenguaje de programación convencional?
En un lenguaje que no tiene una representación nativa, generalmente se agrega usando OOP para crear una clase Complex
para representar i
y j
, con sobrecarga del operador para tratar adecuadamente las operaciones que involucran otros números Complex
u otras primitivas numéricas nativas del idioma. .
Por ejemplo: Complex.java , C ++ <complex>
@Ryan Fox
De hecho, ¿cómo representa uno i (o j para los ingenieros) en un lenguaje de programación convencional?
Los tipos de datos complejos nativos están lejos de ser desconocidos. Fortran lo tuvo a mediados de los años sesenta, y el OP exhibe una variedad de otros lenguajes que los respaldan en el seguimiento histórico.
Y los números complejos se pueden agregar a otros idiomas como bibliotecas (con la sobrecarga del operador incluso se ven como tipos nativos en el código).
Pero a menos que proporcione un caso especial para este problema, el "no acuerdo" es solo una expresión de la aritmética imprecisa de la máquina, ¿no? Es como quejarse de eso
float r = 2/3;
float s = 3*r;
float t = s - 2;
termina con (t! = 0) (Al menos si usa un compilador suficientemente tonto) ...
Aquí hay una breve lista de implementaciones e idiomas que he probado. Se ordena por cercanía a cero:
- Esquema:
(+ 1 (make-polar 1 (atan 0 -1)))
- ⇒
0.0+1.2246063538223773e-16i
(Chez Scheme, esquema MIT) - ⇒
0.0+1.22460635382238e-16i
(Guile) - ⇒
0.0+1.22464679914735e-16i
(pollo connumbers
huevo) - ⇒
0.0+1.2246467991473532e-16i
(MzScheme, SISC, Gauche, Gambit) - ⇒
0.0+1.2246467991473533e-16i
(SCM)
- ⇒
- Common Lisp:
(1+ (exp (complex 0 pi)))
- ⇒
#C(0.0L0 -5.0165576136843360246L-20)
(CLISP) - ⇒
#C(0.0d0 1.2246063538223773d-16)
(CMUCL) - ⇒
#C(0.0d0 1.2246467991473532d-16)
(SBCL)
- ⇒
- Perl:
use Math::Complex; Math::Complex->emake(1, pi) + 1
use Math::Complex; Math::Complex->emake(1, pi) + 1
- ⇒
1.22464679914735e-16i
- ⇒
- Python:
from cmath import exp, pi; exp(complex(0, pi)) + 1
from cmath import exp, pi; exp(complex(0, pi)) + 1
- ⇒
1.2246467991473532e-16j
(CPython)
- ⇒
- Ruby:
require ''complex''; Complex::polar(1, Math::PI) + 1
require ''complex''; Complex::polar(1, Math::PI) + 1
- ⇒
Complex(0.0, 1.22464679914735e-16)
(MRI) - ⇒
Complex(0.0, 1.2246467991473532e-16)
(JRuby)
- ⇒
- R:
complex(argument = pi) + 1
- ⇒
0+1.224606353822377e-16i
- ⇒
Estoy de acuerdo con Ryan, tendrías que pasar a otro sistema de representación numérica. La solución está fuera del ámbito de las matemáticas de punto flotante porque necesita pi para representarse como un decimal infinitamente largo, por lo que cualquier esquema de precisión limitado simplemente no va a funcionar (al menos no sin emplear algún tipo de factor de caramelo para compensar la pérdida precisión).
Su pregunta me parece un poco extraña, ya que parece sugerir que el lenguaje de punto flotante se implementa. Eso generalmente no es cierto, ya que la matemática FP se hace usando un procesador de coma flotante en el hardware. Pero el software o hardware, el punto flotante siempre será inexacto. Así es como funcionan las carrozas.
Si necesita una mayor precisión, debe usar una representación numérica diferente. Como si estuvieras haciendo números enteros en números que no caben en int o long. Algunos idiomas tienen bibliotecas para eso (sé que Java tiene BigInteger y BigDecimal), pero tendrías que usar explícitamente esas bibliotecas en lugar de tipos nativos, y el rendimiento sería (a veces significativamente) peor que si usabas flotantes.
No es que la mayoría de las implementaciones de coma flotante estén en desacuerdo, es solo que no pueden obtener la precisión necesaria para obtener una respuesta del 100%. Y la respuesta correcta es que no pueden.
PI es una serie infinita de dígitos que nadie ha sido capaz de denotar por otra cosa que una representación simbólica, y e ^ X es el mismo, y por lo tanto, la única manera de llegar al 100% de precisión es ir simbólica.
El Análisis Numérico nos enseña que no puede confiar en el valor preciso de las pequeñas diferencias entre los números grandes.
Esto no solo afecta la ecuación en cuestión aquí, sino que puede generar inestabilidad en todo, desde resolver un conjunto casi singular de ecuaciones simultáneas, hasta encontrar los ceros de polinomios, hasta evaluar log (~ 1) o exp (~ 0) ( Incluso he visto funciones especiales para evaluar log (x + 1) y (exp (x) -1) para evitar esto.
Te animo a que no pienses en términos de poner a cero la diferencia, no puedes, sino en hacer los cálculos asociados de manera que se garantice el error mínimo.
Lo siento, han pasado 43 años desde que me tocó este instrumento en la universidad, e incluso si pudiera recordar las referencias, estoy seguro de que ahora hay cosas mejores. Sugiero esto como punto de partida.
Si eso suena un poco condescendiente, me disculpo. Mi "Análisis Numérico 101" fue parte de mi curso de Química, ya que no había mucha CS en esos días. Realmente no tengo una idea del lugar / importancia que tiene el análisis numérico en un curso moderno de CS.
¿Es posible resolver esta disputa?
Mi primer pensamiento es mirar a un lenguaje simbólico, como Maple . Sin embargo, no creo que eso cuente como punto flotante.
De hecho, ¿cómo representa uno i (o j para los ingenieros) en un lenguaje de programación convencional?
Tal vez un mejor ejemplo es sin (π) = 0? (¿O me he perdido el punto otra vez?)
Tuve charlas de café con mi mejor amigo hablando de números irracionales y la diferencia entre otros números. Bueno, ambos estamos de acuerdo en este punto de vista diferente:
Los números irracionales son relaciones, como funciones, de alguna manera, ¿de qué manera? Bueno, piensa en "si quieres un círculo perfecto, dame un pi perfecto", pero los círculos son diferentes a las otras figuras (4 lados, 5, 6 ... 100, 200) pero ... ¿Cuántos lados más? tienes, parece más un círculo. Si me siguieron hasta ahora, conectar todas estas ideas aquí es la fórmula pi:
Entonces, pi es una función, ¡pero una que nunca termina! debido al parámetro,, pero me gusta pensar que puede tener "instancia" de pi, si cambia el parámetro for para un Int muy grande, tendrá una instancia pi muy grande.
Lo mismo con e, dame un parámetro enorme, te daré una gran e.
Juntando todas las ideas:
Como tenemos limitaciones de memoria, el lenguaje y las librerías nos proporcionan una gran instancia de números irracionales, en este caso, pi y e, como resultado final, tendremos un largo acercamiento para obtener 0, como los ejemplos proporcionados por @Chris Jester-Young
Es una limitación de nuestras arquitecturas computacionales actuales de coma flotante. La aritmética de coma flotante es solo una aproximación de polos numéricos como e o pi (o cualquier cosa más allá de la precisión que permiten sus bits). Realmente disfruto estos números porque desafían la clasificación, y parecen tener una mayor entropía (?) Que incluso los números primos, que son una serie canónica. Una representación numérica de la razón desafía, a veces cosas simples como esa pueden volar la mente de una persona (me encanta).
Afortunadamente, idiomas y bibliotecas completos pueden dedicarse a funciones trigonométricas de precisión mediante el uso de conceptos de notación (similares a los descritos por Lasse V. Karlsen ).
Considere una biblioteca / lenguaje que describa conceptos como e y pi en una forma que una máquina pueda entender. ¿Tiene una máquina alguna noción de lo que es un círculo perfecto? Probablemente no, pero podemos crear un objeto - círculo que satisfaga todas las características conocidas que le atribuimos (radio constante, relación de radio a circunferencia es 2 * pi * r = C). Un objeto como pi solo se describe por la relación antes mencionada. Los r & c pueden ser objetos numéricos descritos con la precisión que quieras darles. e se puede definir "como e el número real único tal que el valor de la derivada (pendiente de la línea tangente) de la función f (x) = ex en el punto x = 0 es exactamente 1" desde wikipedia .
Pregunta divertida