@howdypierceHowdy Pierce
Fundador y presidente de la
Mi esposa trae hasta la siguiente historia en cualquier momento que quiere hacer el punto de que soy pedante: Cuando una de mis hijas estaba en segundo grado, a su profesor de matemáticas le dijo a la clase que cualquier número dividido por cero es uno. Le envié un apasionado correo electrónico a la maestra, insistiendo en que el resultado tenía que ser indefinido. Supuestamente esto es evidencia de que a veces es difícil estar cerca de mí.
Resulta que la broma podría recaer en mí, aunque todavía es difícil apoyar la respuesta del maestro de segundo grado. Recientemente aprendí un montón de cosas que no sabía sobre matemáticas de coma flotante:
- Hay un valor para cero negativo, separado de normal (¿positivo?) cero. Estos dos ceros se definen como iguales entre sí y, sin embargo, son valores distintos.
- x ÷ 0.0, para x ≠ ±0.0, no es un error. En cambio, el resultado es infinito positivo o infinito negativo, siguiendo la convención de signos habitual.
- El caso de ±0.0 ÷ ±0.0 es un error (específicamente es «no un número» o NaN).
- -0.0 + -0.0 = -0.0, -0.0 + 0.0 = 0.0, y -0.0 × 0.0 = -0.0
Estas reglas se derivan del IEEE 754 «Estándar para Aritmética de Punto Flotante», que estandarizó las representaciones de punto flotante en todas las plataformas. La versión más reciente del estándar se completó en 2008, pero la versión original se publicó en 1985, por lo que este comportamiento no es nuevo. Las reglas anteriores son válidas tanto en C (gcc) como en Swift en mi Mac, y también son válidas en Swift en un iPhone. Python en Mac admite cero negativo para flotadores, pero lanza una excepción cuando intenta dividir por cero de cualquier signo.
Hay un par de corolarios sorprendentes para estas reglas:
- Porque 0.0 y -0.0 deben compararse como iguales, la prueba (x < 0.0) no devuelve verdadero para cada número negativo, falla para cero negativo. Por lo tanto, para determinar el signo de un valor cero, debe usar la función de signo incorporada de la plataforma, por ejemplo, Double.inicia sesión Swift. O supongo que podrías manipular en bits la representación en bruto del doble, que es en gran medida la respuesta de un programador de C.
- Si a = b ÷ c, no necesariamente se sigue que b = a × c, porque esto también falla para el caso en que c es un cero de cualquier signo.
No soy un teórico de números, pero encuentro los conceptos anteriores sorprendentes.
Un problema inmediato: Infinito no es un número, como cero o 3.25 o π. Más bien, el infinito es un concepto. Es cierto que los números racionales son infinitos, pero el infinito no es un miembro del conjunto de números racionales.
Además, desde la perspectiva de la teoría de números, la división por cero no tiene sentido. Puedes entender por qué si eres preciso sobre lo que significa división. Técnicamente, » división «es» multiplicación por el inverso de un número», donde el inverso satisface: a × a^-1 = 1. Cero es el único número en el conjunto de números reales que simplemente no tiene inverso multiplicativo. Y como este inverso no existe, no podemos multiplicarlo por él.
Pero seguramente la gente que diseñó los números de coma flotante sabía todo esto. Por lo tanto, me preguntaba por qué el comportamiento descrito se escribió en el estándar IEEE.
Para empezar, consideremos el problema que la matemática de coma flotante está tratando de resolver. Los números reales son infinitos incontables, y sin embargo deseamos representar todo este conjunto dentro de los límites de la memoria finita de la computadora. Con un doble de 64 bits, hay 2^64 símbolos posibles, y los diseñadores del estándar IEEE estaban tratando de mapear estos símbolos en el conjunto de números reales de una manera que fuera útil para aplicaciones del mundo real y también económicamente viable dadas las limitaciones del silicio de principios de los 80. Dados los requisitos básicos, se iban a utilizar claramente aproximaciones.
El razonamiento para cero negativo parece fecharse en un artículo de 1987 de William Kahan, un profesor de Berkeley que es considerado el «padre del punto flotante» y que más tarde ganó el Premio Turing por su trabajo en la redacción de IEEE 754. Resulta que la existencia de cero negativo está íntimamente ligada a la capacidad de dividir por cero.
Comencemos por discutir la razón habitual por la que no se permite la división por cero. Un enfoque ingenuo de la división por cero es la observación de que:
En otras palabras, a medida que x se hace más pequeño, el resultado de 1/x se hace más grande. Pero esto solo es cierto cuando x se acerca a 0 desde el lado positivo (por lo que hay ese pequeño signo más de arriba). Ejecutar el mismo experimento mental desde el lado negativo:
Como resultado, el límite genérico de 1/x a medida que x se acerca a 0 no está definido, porque hay una discontinuidad (lo que Kahan llama una ranura) en la función 1/x.
Sin embargo, al introducir un cero firmado, Kahan y el comité IEEE podrían solucionar la dificultad. Intuitivamente, el signo de un cero se toma para indicar la dirección desde la que se está acercando el límite. Como afirma Kahan en su artículo de 1987:
En lugar de pensar en +0 y -0 como valores numéricos distintos, piense en su bit de signo como una variable auxiliar que transmite un bit de información (o información errónea) sobre cualquier variable numérica que tome 0 como su valor. Generalmente esta información es irrelevante; el valor de 3+x no es diferente de x := +0 que para x := -0…. Sin embargo, algunas operaciones aritméticas extraordinarias se ven afectadas por el signo de cero; por ejemplo, 1/ (+0) = +∞ pero 1/ (-0) = –∞.
He hecho las paces con el concepto adoptando una racionalización propuesta por mi socio Mike Perkins: Los 2^64 símbolos disponibles son claramente inadecuados para representar la totalidad del conjunto de números reales. Por lo tanto, los diseñadores de IEEE reservaron algunos de esos símbolos para significados especiales. En este sentido, ∞ no significa realmente «infinito», sino que significa » un número real que es más grande de lo que podemos representar en nuestro conjunto de símbolos de punto flotante.»Y por lo tanto, +0 no significa realmente» cero», sino más bien » un número real que es mayor que 0 verdadero pero menor que cualquier número positivo que podamos representar.»
Por cierto, mientras investigaba este tema, descubrí que incluso a Kahan no le gusta la idea de cero negativo:
Cero firmado — bueno, el cero firmado era un dolor de cabeza que podríamos eliminar si usáramos el modo proyectivo. Si solo hubiera un infinito y un cero, podrías hacerlo bien; entonces no te importaba el signo de cero y no te importaba el signo de infinito. Pero si, por otro lado, insististe en lo que yo habría considerado como la elección menor de dos infinitos, entonces vas a terminar con dos ceros firmados. Realmente no había una manera de evitarlo y estabas atascado con eso.»(De una entrevista de Kahan realizada en 2005.)
No estoy seguro de si escribir una publicación de blog diez años después compensa las críticas a un maestro de segundo grado pobre. Por su parte, mi hija, ahora en la escuela secundaria, simplemente puso los ojos en blanco cuando empecé a hablar de división por cero en la cena. Así que tal vez esa cosa de «difícil estar cerca» es hereditaria.
Kahan, W., «Branch Cuts for Complex Elementary Functions, or Much Ado About Nothing’s Sign Bit», The State of the Art in Numerical Analysis, (Eds. Iserles y Powell), Clarendon Press, Oxford, 1987, disponible aquí.
Tags
Create your free cuenta para desbloquear tu experiencia de lectura personalizada.