Estaba viendo http://www.joelonsoftware.com/items/2011/06/27.html y me reí de la broma de Jon Skeet acerca de que 0.3 no era 0.3. Personalmente nunca tuve problemas con flotadores / decimales / dobles, pero recuerdo que aprendí 6502 muy temprano y nunca necesité flotadores en la mayoría de mis programas. La única vez que lo usé fue para gráficos y matemáticas donde los números inexactos estaban bien y la salida era para la pantalla y no para ser almacenada (en un archivo de base de datos) o dependiente.
Mi pregunta es, ¿dónde están los lugares donde solía usar flotantes / decimales / dobles? Así que sé tener cuidado con estas trampas. Con dinero uso valores largos y valores de almacenamiento por centavo, para la velocidad de un objeto en un juego agrego entradas y divido (o cambio de bits) el valor para saber si necesito mover un píxel o no. (Hice un movimiento de objetos en los 6502 días, no tuvimos divisiones ni flotadores, pero tuvimos turnos).
Así que tenía mucha curiosidad.
fuente
Respuestas:
Porque son, para la mayoría de los propósitos, más precisos que los enteros.
Ahora como es eso? "para la velocidad de un objeto en un juego ..." este es un buen ejemplo para tal caso. Digamos que necesita tener algunos objetos muy rápidos, como balas. Para poder describir su movimiento con variables de velocidad enteras, debe asegurarse de que las velocidades estén en el rango de las variables enteras, eso significa que no puede tener un ráster arbitrariamente fino.
Pero entonces, es posible que también desee describir algunos objetos muy lentos, como la manecilla de la hora de un reloj. Como esto es aproximadamente 6 órdenes de magnitud más lento que los objetos de bala, los primeros ld (10⁶) ≈ 20 bits son cero, lo que descarta los
short int
tipos desde el principio. Ok, hoy tenemoslong
s en todas partes, lo que nos deja con 12 bits aún cómodos. Pero incluso entonces, la velocidad del reloj será exacta a solo cuatro decimales. Ese no es un reloj muy bueno ... pero ciertamente está bien para un juego. Simplemente, no querrás hacer que la trama sea mucho más gruesa de lo que ya es.... lo que genera problemas si algún día desea introducir un nuevo tipo de objeto aún más rápido. No queda "espacio libre".
¿Qué sucede si elegimos un tipo de flotador? Mismo tamaño de 32 bits, pero ahora tiene una precisión total de 24 bits para todos los objetos. Eso significa que el reloj tiene la precisión suficiente para mantenerse sincronizado al instante durante años. Las balas no tienen mayor precisión, pero solo "viven" por fracciones de segundo de todos modos, por lo que sería completamente inútil si lo tuvieran. Y no se mete en ningún tipo de problema si desea describir objetos aún más rápidos (¿por qué no la velocidad de la luz? No hay problema) o mucho más lentos. Ciertamente no necesitarás tales cosas en un juego, pero a veces sí las necesitas en simulaciones físicas.
Y con los números de coma flotante, obtienes esta misma precisión siempre y sin tener que elegir inteligentemente algún ráster no obvio. Ese es quizás el punto más importante, ya que tales necesidades de elección son muy propensas a errores.
fuente
Los usa cuando describe un valor continuo en lugar de uno discreto . No es más complicado de describir que eso. Simplemente no cometa el error de asumir que cualquier valor con un punto decimal es continuo. Si cambia todo a la vez en trozos, como agregar un centavo, es discreto.
fuente
Realmente tienes dos preguntas aquí.
¿Por qué alguien necesita matemática de punto flotante, de todos modos?
Como señala Karl Bielefeldt, los números de coma flotante le permiten modelar cantidades continuas, y las encuentra por todas partes, no solo en el mundo físico, sino incluso en lugares como negocios y finanzas.
He usado matemática de punto flotante en muchas, muchas áreas en mi carrera de programación: química, trabajando en AutoCAD e incluso escribiendo un simulador de Monte Carlo para hacer predicciones financieras. De hecho, hay un tipo llamado David E. Shaw que utilizó técnicas de modelado científico basadas en coma flotante en Wall Street para generar miles de millones.
Y, por supuesto, hay gráficos por computadora. Consulté sobre el desarrollo de los dulces visuales para las interfaces de usuario, y tratar de hacerlo hoy en día sin una sólida comprensión de coma flotante, trigonometría, cálculo y álgebra lineal, sería como presentarse a un tiroteo con una navaja.
¿Por qué alguien necesitaría un flotador frente a un doble ?
Con las representaciones estándar IEEE 754, un flotante de 32 bits le proporciona aproximadamente 7 dígitos decimales de precisión y exponentes en el rango de 10 -38 a 10 38 . Un doble de 64 bits le proporciona aproximadamente 15 dígitos decimales de precisión y exponentes en el rango de 10-307 a 10 307 .
Puede parecer que un flotador sería suficiente para lo que alguien razonablemente necesitaría, pero no lo es. Por ejemplo, muchas cantidades del mundo real se miden en más de 7 dígitos decimales.
Pero más sutilmente, hay un problema coloquialmente llamado "error de redondeo". Las representaciones de punto flotante binario solo son válidas para valores cuyas partes fraccionarias tienen un denominador que tiene una potencia de 2, como 1/2, 1/4, 3/4, etc. Para representar otras fracciones, como 1/10, "redondeas" el valor de la fracción binaria más cercana, pero está un poco mal: ese es el "error de redondeo". Luego, cuando haces cálculos matemáticos con esos números inexactos, las inexactitudes en los resultados pueden ser mucho peores de lo que comenzaste, a veces los porcentajes de error se multiplican o incluso se acumulan exponencialmente.
De todos modos, cuantos más dígitos binarios tenga que trabajar, más cercana será su representación binaria redondeada al número que está tratando de representar, por lo que su error de redondeo será menor. Luego, cuando hace cálculos matemáticos, si tiene muchos dígitos con los que trabajar, puede realizar muchas más operaciones antes de que el error de redondeo acumulado se acumule donde es un problema.
En realidad, los dobles de 64 bits con sus 15 dígitos decimales no son lo suficientemente buenos para muchas aplicaciones. Estaba usando números de punto flotante de 80 bits en 1985, y IEEE ahora define un tipo de punto flotante de 128 bits (16 bytes), para el cual puedo imaginar usos.
fuente
Es una idea falsa común, que en todas partes donde se trata con dinero, debe almacenar su valor como entero (centavos). Si bien en algunos casos simples como la tienda en línea es cierto, si tiene algo más avanzado, no ayuda mucho.
Veamos un ejemplo: un desarrollador gana $ 100,000 al año. ¿Cuál es el salario exacto de su mes? Con el número entero obtienes el resultado $ 8333.33 (¢ 833333), que multiplicado por 12 es $ 99,999.96. ¿Mantenerlo como entero ayuda? No, no lo hizo.
¿Los bancos siempre usan valores decimales / enteros? Bueno, lo hacen por parte transaccional. Pero, por ejemplo, tan pronto como comience a hablar de banca de inversión, con la excepción de realizar un seguimiento de las transacciones reales, todo lo demás es flotante. Dado que todo es código interno, no lo verá, pero puede tomar un pico en QuantLib , que es esencialmente el mismo (excepto mucho más limpio ;-).
¿Por qué usar flotadores? Porque usar decimal no ayuda en absoluto cuando usas funciones como raíz cuadrada, logaritmos, potencias con exponentes no enteros, etc. Y, por supuesto, los flotadores son mucho más rápidos que los tipos decimales.
fuente
$100,000/12
y usaste una carroza. ¿Por qué el resultado sería exactamente $ 100,000? ¿Por qué el flotador (o decimal) no se redondea hacia arriba o hacia abajo cada vez que alguien paga? Me refiero a la hora de escribir un cheque (no puedes hacer 1/2 o 1/3 de un centavo) o un depósito directo (supongo que tiene las mismas limitaciones)Lo que ha descrito son soluciones perfectamente buenas para situaciones en las que controla todas las entradas y salidas .
En la palabra real no es el caso. Deberá poder hacer frente a los sistemas que le proporcionan sus datos como un valor real con cierto grado de precisión y esperará que devuelva los datos en el mismo formato. En tales casos , encontrará estos problemas.
De hecho, encontrará estos problemas incluso si utiliza los trucos que enumera. Al calcular el impuesto del 17.5% sobre un precio, obtendrá centavos fraccionales, ya sea que almacene el valor en dólares o centavos. Debe redondear correctamente ya que el recaudador de impuestos se molesta mucho si no le paga lo suficiente. Usar los
money
tipos correctos (cualesquiera que sean en el idioma que está usando) lo salvará de un mundo de dolor.fuente
"Dios creó los números enteros, todo lo demás es obra del hombre". - Leopold Kronecker (1886).
Por definición, no necesita ningún otro tipo de números. La integridad de Turing para un lenguaje de programación se basa en las relaciones simples entre los diversos tipos de números. Si puede trabajar con números enteros (a / k / a números naturales), puede hacer cualquier cosa.
La pregunta es un poco engañosa porque no los necesitas . ¿Quizás quieres lugares donde sea conveniente u óptimo o más barato o algo así?
fuente
En una oración, los tipos decimales de coma flotante encapsulan la conversión hacia y desde valores enteros (que es todo lo que la computadora sabe cómo tratar en el nivel binario; no hay punto decimal en binario) proporcionando una lógica, generalmente fácil de entender. Comprender la interfaz para los cálculos de números decimales.
Francamente, decir que no necesitas flotadores porque sabes cómo hacer cálculos decimales con números enteros es como decir que sabes hacer aritmética a mano, entonces, ¿por qué usar una calculadora? Entonces conoces el concepto; Bravo. No significa que tenga que ejercer ese conocimiento todo el tiempo. A menudo es más rápido, más barato y más comprensible para un genio no binario decir simplemente 3.5 + 4.6 = 8.1 en lugar de convertir los higos a una cantidad entera.
fuente
La principal ventaja de los tipos de punto flotante es que, desde una perspectiva de tiempo de ejecución, dos o tres formatos (deseo que más idiomas admitan formatos de 80 bits) serán suficientes para la mayoría rápida de los propósitos computacionales. Si los lenguajes de programación pudieran admitir fácilmente una familia de tipos de punto fijo, la complejidad del hardware requerida para un nivel de rendimiento dado a menudo sería menor con los tipos de punto fijo que con el punto flotante. Desafortunadamente, proporcionar tal soporte está lejos de ser "fácil".
Para que un lenguaje de programación satisfaga eficientemente el 98% de las necesidades numéricas de las aplicaciones, tendría que incluir docenas de tipos y proporcionar operaciones definidas para lo que pueden ser cientos de combinaciones; Además, incluso si un lenguaje de programación tuviera un maravilloso soporte de punto fijo, algunas aplicaciones aún tendrían que mantener una precisión relativa aproximadamente constante en un rango lo suficientemente grande como para requerir punto flotante. Dado que las matemáticas de punto flotante serán necesarias en algunas ocasiones en cualquier caso, hacer que los proveedores de hardware se centren en el rendimiento matemático con dos o tres formatos de punto flotante y que el código use esos formatos siempre que funcionen razonablemente bien, generalmente logrará mejores resultados. "aprovechar el dinero" de lo que trataría de optimizar el comportamiento de las matemáticas de punto fijo.
Por cierto, las matemáticas de punto fijo fueron más ventajosas con los procesadores de 8 y 16 bits que con los de 32 bits. En un procesador de 8 bits, en una situación en la que 32 bits no serían suficientes, un tipo de 40 bits solo costaría un 25% más de espacio y un 25-50% más de tiempo que el tipo de 32 bits, y requeriría un 37,5% menos espacio y 37.5-60% menos tiempo que un tipo de 64 bits. En una plataforma de 32 bits, si un tipo de 32 bits no es suficiente para algo, a menudo hay pocas razones para usar algo de menos de 64 bits. Si un tipo de punto fijo de 48 bits fuera adecuado, un "doble" de 64 bits funcionará tan bien como el tipo de punto fijo.
fuente
En general, debe tener mucho cuidado al usarlos. Comprender la pérdida de precisión que puede surgir incluso de cálculos simples es un desafío. Por ejemplo, promediar una lista de números como esta es una muy mala idea:
La razón es que, para listas lo suficientemente grandes, básicamente pierde todos los puntos de datos cuando
ans
es lo suficientemente grande (ver, por ejemplo, esto ). El problema con este código es que para listas pequeñas, probablemente solo funcionará, solo se rompe a escala.Personalmente, creo que solo debe usarlos cuando: a) el cálculo realmente debe ser rápido; b) no le importa que el resultado sea muy diferente (a menos que realmente sepa lo que está haciendo).
fuente
Un pensamiento es que usaría las representaciones flotantes o dobles cuando necesite tratar con valores fuera del rango entero.
Las arquitecturas actuales (aproximadamente) tienen un rango entero con signo de +/- 2.147.483.647 (32 bits) o +/- 9.223.372.036.854.775.807 (64 bits). Unsigned extiende eso por un factor de 2.
Los flotadores IEEE 754 (aproximadamente) van desde +/- 1.4 × 10 ^ −45 a 3.4 × 10 ^ 38. Double extiende ese rango a +/- 5 × 10−324 ± 2.225 × 10 ^ −308 con muchas condiciones y detalles omitidos aquí.
Por supuesto, la razón más asombrosamente obvia es que es posible que deba representar -0 ;-)
fuente
La razón habitual es porque son rápidos, ya que la JVM generalmente usa soporte de hardware subyacente (a menos que use estrictamente fp).
Vea /programming/517915/when-to-use-strictfp-keyword-in-java para lo que implicatricfp.
fuente
Es por eso que necesitamos sistemas operativos de 256 bits.
La longitud del tablón (la distancia más pequeña que puede medir) = 10 ^ -35m
El universo observable es 14Bn parsecs de ancho = 10 ^ 25m
Para que pueda medir cualquier cosa en unidades de la longitud del tablón como enteros si tiene solo 200 bits de precisión.
fuente