¿Qué se puede hacer con los lenguajes de programación para evitar dificultades de coma flotante?

28

El malentendido de la aritmética de coma flotante y sus defectos es una de las principales causas de sorpresa y confusión en la programación (considere el número de preguntas sobre el desbordamiento de pila relacionadas con "números que no suman correctamente"). Teniendo en cuenta que muchos programadores aún no han entendido sus implicaciones, tiene el potencial de introducir muchos errores sutiles (especialmente en el software financiero). ¿Qué pueden hacer los lenguajes de programación para evitar sus dificultades para aquellos que no están familiarizados con los conceptos, mientras ofrecen su velocidad cuando la precisión no es crítica para aquellos que entienden los conceptos?

Adam Paynter
fuente
26
Lo único que puede hacer un lenguaje de programación para evitar las trampas del procesamiento de punto flotante es prohibirlo. Tenga en cuenta que esto también incluye el punto flotante de base 10, que en general es igual de impreciso, excepto que las aplicaciones financieras están preadaptadas.
David Thornley
44
Para eso sirve el "Análisis numérico". Aprenda a minimizar la pérdida de precisión, también conocida como trampas de punto flotante.
Un buen ejemplo de un problema de coma flotante: stackoverflow.com/questions/10303762/0-0-0-0-0
Austin Henley

Respuestas:

47

Usted dice "especialmente para el software financiero", lo que saca a relucir una de mis manías: el dinero no es un flotador, es un int .

Claro, parece un flotador. Tiene un punto decimal allí. Pero eso es solo porque estás acostumbrado a unidades que confunden el problema. El dinero siempre viene en cantidades enteras. En Estados Unidos, son centavos. (En ciertos contextos, creo que pueden ser molinos , pero ignore eso por ahora).

Entonces, cuando dices $ 1.23, eso es realmente 123 centavos. Siempre, siempre, siempre haz tus cálculos en esos términos, y estarás bien. Para más información, ver:

Respondiendo la pregunta directamente, los lenguajes de programación deberían incluir un tipo de dinero como una primitiva razonable.

actualizar

Ok, debería haber dicho "siempre" dos veces, en lugar de tres veces. El dinero es siempre un int; los que piensan lo contrario pueden enviarme 0,3 centavos y mostrarme el resultado en su extracto bancario. Pero como señalan los comentaristas, hay raras excepciones cuando necesitas hacer cálculos de coma flotante en números similares a dinero. Por ejemplo, ciertos tipos de precios o cálculos de intereses. Incluso entonces, esos deben ser tratados como excepciones. El dinero entra y sale como cantidades enteras, por lo que cuanto más se acerque su sistema a eso, más seguro será.

William Pietri
fuente
20
@JoelFan: estás confundiendo un concepto con una implementación específica de la plataforma.
cuál es el
12
No es tan simple. Los cálculos de intereses, entre otros, producen centavos fraccionales, y deben redondearse en algún momento de acuerdo con un método específico.
Kevin Cline
24
Ficticio -1, ya que me falta el representante para un voto negativo :) ... Esto podría ser correcto para lo que sea que esté en su billetera, pero hay muchas situaciones contables en las que bien podría estar lidiando con décimas de centavo o fracciones más pequeñas. Decimales el único sistema sensato para lidiar con esto, y su comentario "ignorar eso por ahora" es el heraldo de la fatalidad para los programadores de todas partes: P
detly
99
@kevin cline: Hay centavos fraccionales en los cálculos, pero hay convenciones sobre cómo manejarlos. El objetivo para los cálculos financieros no es la corrección matemática, sino obtener los mismos resultados exactos que un banco con una calculadora.
David Thornley
66
Todo será perfecto reemplazando la palabra "entero" por "racional" -
Emilio Garavaglia
15

Proporcionar soporte para un tipo decimal ayuda en muchos casos. Muchos idiomas tienen un tipo decimal, pero están infrautilizados.

Comprender la aproximación que ocurre cuando se trabaja con representación de números reales es importante. Usar ambos tipos de coma decimal y coma flotante 9 * (1/9) != 1es una declaración correcta. Cuando las constantes, un optimizador puede optimizar el cálculo para que sea correcto.

Proporcionar un operador aproximado ayudaría. Sin embargo, tales comparaciones son problemáticas. Tenga en cuenta que .9999 billones de dólares es aproximadamente igual a 1 billón de dólares. ¿Podría depositar la diferencia en mi cuenta bancaria?

BillThor
fuente
2
0.9999...billones de dólares es exactamente igual a 1 billón de dólares en realidad.
SOLO MI OPINIÓN correcta
55
@ SOLO: Sí, pero no he encontrado ninguna computadora con registros que aguanten 0.99999.... Todos se truncan en algún momento, lo que resulta en una desigualdad. 0.9999es lo suficientemente igual para la ingeniería. Para fines financieros no lo es.
BillThor
2
Pero, ¿qué tipo de sistema utilizaba billones de dólares como unidad base en lugar de dólares?
Brad
@Brad Intenta calcular (1 billón / 3) * 3 en tu calculadora. ¿Qué valor obtienes?
BillThor
8

Cuando fui a la universidad, nos dijeron qué hacer en la clase de primer año (segundo año) de ciencias de la computación (este curso también era un requisito previo para la mayoría de los cursos de ciencias)

Recuerdo que el profesor dijo: "Los números en coma flotante son aproximaciones. Use tipos enteros para obtener dinero. Use FORTRAN u otro lenguaje con números BCD para un cálculo preciso". (y luego señaló la aproximación, usando ese ejemplo clásico de 0.2 imposible de representar con precisión en coma flotante binaria). Esto también apareció esa semana en los ejercicios de laboratorio.

Misma conferencia: "Si debe obtener más precisión del punto flotante, ordene sus términos. Agregue números pequeños, no números grandes". Eso se me quedó grabado.

Hace unos años tenía una geometría esférica que necesitaba ser muy precisa y rápida. El doble de 80 bits en las PC no era suficiente, así que agregué algunos tipos al programa que clasificaron los términos antes de realizar operaciones conmutativas. Problema resuelto.

Antes de quejarse de la calidad de la guitarra, aprenda a tocar.

Hace cuatro años, tuve un compañero de trabajo que había trabajado para JPL. Expresó su incredulidad porque usamos FORTRAN para algunas cosas. (Necesitábamos simulaciones numéricas súper precisas calculadas fuera de línea). "Reemplazamos todo ese FORTRAN con C ++", dijo con orgullo. Dejé de preguntarme por qué se perdieron un planeta.

Tim Williscroft
fuente
2
+1 la herramienta adecuada para el trabajo correcto. Aunque en realidad no uso FORTRAN. Afortunadamente, tampoco trabajo en nuestros sistemas financieros en el trabajo.
James Khoury
"Si debe obtener más precisión desde el punto flotante, ordene sus términos. Agregue números pequeños juntos, no a números grandes". ¿Alguna muestra de esto?
mamcx
@mamcx Imagine un número decimal en coma flotante con solo un dígito de precisión. El cálculo 1.0 + 0.1 + ... + 0.1(repetido 10 veces) regresa a 1.0medida que se redondea cada resultado intermedio. Hacerlo al revés, se obtiene resultados intermedios de 0.2, 0.3, ..., 1.0y finalmente 2.0. Este es un ejemplo extremo, pero con números realistas de coma flotante, ocurren problemas similares. La idea base es que agregar números de tamaño similar conduce al error más pequeño. Comience con los números más pequeños ya que su suma es mayor y, por lo tanto, es más adecuada para sumar a los más grandes.
maaartinus
Sin embargo, las cosas de punto flotante en Fortran y C ++ serán en su mayoría idénticas. Ambos son precisos y sin conexión, y estoy bastante seguro de que Fortran no tiene reales BCD nativos ...
Mark
8

Advertencia: El sistema de tipo de punto flotante. Doble carece de la precisión para la prueba de igualdad directa.

double x = CalculateX();
if (x == 0.1)
{
    // ............
}

No creo que se pueda o deba hacer nada a nivel de idioma.

ChaosPandion
fuente
1
No he usado flotador o doble en mucho tiempo, así que tengo curiosidad. ¿Es esa una advertencia del compilador existente real o solo una que le gustaría ver?
Karl Bielefeldt
1
@Karl - Personalmente no lo he visto ni lo necesito, pero imagino que podría ser útil para desarrolladores dedicados pero ecológicos.
ChaosPandion
1
Los tipos de punto flotante binario no son mejores o peores cualitativamente que Decimalcuando se trata de pruebas de igualdad. La diferencia entre 1.0m/7.0m*7.0my 1.0mpuede ser muchos órdenes de magnitud menor que la diferencia entre 1.0/7.0*7.0, pero no es cero.
supercat
1
@Patrick: no estoy seguro de a qué te refieres. Hay una gran diferencia entre que algo es cierto para un caso y ser cierto para todos los casos.
ChaosPandion
1
@ChaosPandion El problema con el ejemplo en esta publicación no es la comparación de igualdad, es el literal de coma flotante. No hay flotante con el valor exacto 1.0 / 10. La matemática de punto flotante da como resultado resultados 100% precisos cuando se computa con números enteros que se ajustan dentro de la mantisa.
Patrick
7

De forma predeterminada, los idiomas deben usar razones de precisión arbitraria para números no enteros.

Aquellos que necesitan optimizar siempre pueden pedir flotadores. Usarlos por defecto tiene sentido en C y otros lenguajes de programación de sistemas, pero no en la mayoría de los lenguajes populares hoy en día.

Waquo
fuente
1
¿Cómo manejas los números irracionales entonces?
dsimcha
3
Lo haces de la misma manera que con los flotadores: aproximación.
Waquo
1
Tengo que decir que creo que esto tiene mucho sentido, la mayoría de las personas que necesitan números exactos necesitan racionales, no irracionales (la ciencia y la ingeniería pueden usar irracionales, pero luego vuelves al reino aproximado, o estás haciendo matemáticas puras bastante especializadas)
jk.
1
Los cálculos con racionales de precisión arbitraria a menudo serán órdenes de magnitud más lentos (posiblemente MUCHOS órdenes de magnitud más lentos) que los cálculos con soporte de hardware double. Si un cálculo necesita ser exacto a una parte por millón, es mejor gastar un microsegundo informándolo dentro de unas pocas partes por billón, que gastar un segundo informándolo de manera absolutamente precisa.
supercat
55
@supercat: Lo que estás sugiriendo es solo un póster de optimización prematura. La situación actual es que la gran mayoría de los programadores no tienen necesidad de matemática rápida, y luego son mordidos por un comportamiento de punto flotante (erróneo) difícil de entender, de modo que el número relativamente pequeño de programadores que necesitan matemática rápida lo obtienen sin tener para escribir un solo personaje extra. Esto tenía sentido en los años setenta, ahora es una tontería. El valor predeterminado debería ser seguro. Aquellos que necesitan ayunar deben pedirlo.
Waquo
4

Los dos mayores problemas relacionados con los números de coma flotante son:

  • unidades inconsistentes aplicadas a los cálculos (tenga en cuenta que esto también afecta a la aritmética de enteros de la misma manera)
  • no entender que los números FP son una aproximación y cómo lidiar inteligentemente con el redondeo.

El primer tipo de falla solo puede remediarse proporcionando un tipo compuesto que incluya información sobre el valor y la unidad. Por ejemplo, un valor lengtho areaque incorpora la unidad (metros o metros cuadrados o pies y pies cuadrados respectivamente). De lo contrario, debe ser diligente para trabajar siempre con un tipo de unidad de medida y solo para convertir a otro cuando compartimos la respuesta con un humano.

El segundo tipo de falla es una falla conceptual. Las fallas se manifiestan cuando la gente piensa en ellas como números absolutos . Afecta las operaciones de igualdad, los errores de redondeo acumulativo, etc. Por ejemplo, puede ser correcto que para un sistema dos mediciones sean equivalentes dentro de un cierto margen de error. Es decir .999 y 1.001 son más o menos lo mismo que 1.0 cuando no le importan las diferencias que son más pequeñas que +/- .1. Sin embargo, no todos los sistemas son tan indulgentes.

Si se necesita alguna facilidad de nivel de idioma, entonces lo llamaría precisión de igualdad . En NUnit, JUnit y marcos de prueba construidos de manera similar, puede controlar la precisión que se considera correcta. Por ejemplo:

Assert.That(.999, Is.EqualTo(1.001).Within(10).Percent);
// -- or --
Assert.That(.999, Is.EqualTo(1.001).Within(.1));

Si, por ejemplo, C # o Java se modificaron para incluir un operador de precisión, podría verse así:

if(.999 == 1.001 within .1) { /* do something */ }

Sin embargo, si proporciona una característica como esa, también debe considerar el caso en que la igualdad es buena si los lados +/- no son iguales. Por ejemplo, + 1 / -10 consideraría dos números equivalentes si uno de ellos estuviera dentro de 1 más, o 10 menos que el primer número. Para manejar este caso, es posible que también deba agregar una rangepalabra clave:

if(.999 == 1.001 within range(.001, -.1)) { /* do something */ }
Berin Loritsch
fuente
2
Cambiaría el orden. El problema conceptual es generalizado. El problema de conversión de unidades es relativamente menor en comparación.
S.Lott
Me gusta el concepto de operador de precisión, pero como mencionas más adelante, definitivamente necesitaría estar bien pensado. Personalmente, estaría más inclinado a verlo como su propia construcción sintáctica completa.
ChaosPandion
También podría hacerse muy fácilmente en una biblioteca.
Michael K
1
@ dan04: Estaba pensando más en términos de "todos los cálculos con precisión dentro del uno por ciento" o similares. He visto el pozo de alquitrán que es el manejo de la unidad de medida y me estoy quedando lejos.
TMN
1
Hace unos 25 años, vi un paquete numérico con un tipo que consta de un par de números de coma flotante que representan los valores máximos y mínimos posibles para una cantidad. A medida que los números pasaban por los cálculos, la diferencia entre máximo y mínimo crecería. Efectivamente, esto proporcionó un medio para saber cuánta precisión real estaba presente en un valor calculado.
supercat
3

¿Qué pueden hacer los lenguajes de programación? No sé si hay una respuesta a esa pregunta, porque cualquier cosa que el compilador / intérprete haga en nombre del programador para facilitarle la vida generalmente va en contra del rendimiento, la claridad y la legibilidad. Creo que tanto la forma C ++ (pague solo por lo que necesita) como la forma Perl (principio de menor sorpresa) son válidas, pero depende de la aplicación.

Los programadores aún necesitan trabajar con el lenguaje y comprender cómo maneja los puntos flotantes, porque si no lo hacen, harán suposiciones, y un día el comportamiento perscrito no coincidirá con sus suposiciones.

Mi opinión sobre lo que el programador necesita saber:

  • Qué tipos de punto flotante están disponibles en el sistema y en el idioma
  • Que tipo es necesario
  • Cómo expresar las intenciones de qué tipo se necesita en el código
  • Cómo aprovechar correctamente cualquier tipo de promoción automática para equilibrar la claridad y la eficiencia, manteniendo la corrección
John
fuente
3

¿Qué pueden hacer los lenguajes de programación para evitar dificultades [de punto flotante] ...?

Utilice valores predeterminados razonables, por ejemplo, soporte integrado para decimales.

Groovy hace esto bastante bien, aunque con un poco de esfuerzo aún puede escribir código para introducir imprecisión de coma flotante.

Armand
fuente
3

Estoy de acuerdo en que no hay nada que hacer a nivel de idioma. Los programadores deben comprender que las computadoras son discretas y limitadas, y que muchos de los conceptos matemáticos representados en ellas son solo aproximaciones.

No importa el punto flotante. Hay que entender que la mitad de los patrones de bits se usan para números negativos y que 2 ^ 64 es en realidad bastante pequeño para evitar problemas típicos con la aritmética de enteros.

revs Apalala
fuente
no está de acuerdo, la mayoría de los idiomas actualmente dan demasiado soporte para los tipos de coma flotante binarios (¿por qué == incluso se define para flotantes?) y no hay suficiente soporte para racionales o decimales
jk.
@jk: incluso si el resultado de cualquier cálculo nunca se garantizara igual al resultado de cualquier otro cálculo, la comparación de igualdad aún sería útil para el caso en el que se asigna el mismo valor a dos variables (aunque las reglas de igualdad comúnmente implementadas son quizás demasiado flojo, ya que x== yno implica que realizar un cálculo en xproducirá el mismo resultado que realizar el mismo cálculo en y).
supercat
@supercat todavía necesita comparación, pero prefiero que el lenguaje requiera que especifique una tolerancia para cada comparación de coma flotante, todavía puedo volver a la igualdad eligiendo tolerancia = 0, pero al menos me veo obligado a hacerlo elección
jk.
3

Una cosa que podrían hacer los idiomas: eliminar la comparación de igualdad de los tipos de punto flotante que no sea una comparación directa con los valores NAN.

La prueba de igualdad solo existiría es como una llamada de función que tomó los dos valores y un delta, o para lenguajes como C # que permiten que los tipos tengan métodos un EqualsTo que toma el otro valor y el delta.

Loren Pechtel
fuente
3

Me resulta extraño que nadie haya señalado el truco racional de la familia Lisp.

En serio, abre sbcl y haz esto: (+ 1 3)y obtienes 4. Si *( 3 2)obtienes 6. Ahora intenta (/ 5 3)y obtienes 5/3, o 5 tercios.

Eso debería ayudar un poco en algunas situaciones, ¿no?

Haakon Løtveit
fuente
Me pregunto, si es posible saber si un resultado debe representarse como 1/3 o podría ser un decimal exacto.
mamcx
buena sugerencia
Peter Porfy
3

Una cosa que me gustaría ver sería un reconocimiento de que doublea floatdebe ser considerada como una conversión de ampliación, mientras floatque doublese está estrechando (*). Eso puede parecer contrario a la intuición, pero considere lo que realmente significan los tipos:

  • 0.1f significa "13,421,773.5 / 134,217,728, más o menos 1 / 268,435,456 más o menos".
  • 0.1 realmente significa 3,602,879,701,896,397 / 36,028,797,018,963,968, más o menos 1 / 72,057,594,037,927,936 más o menos "

Si uno tiene una doubleque tiene la mejor representación de la cantidad "una décima" y la convierte float, el resultado será "13,421,773.5 / 134,217,728, más o menos 1 / 268,435,456 más o menos", que es una descripción correcta del valor.

Por el contrario, si uno tiene una floatque tiene la mejor representación de la cantidad "una décima" y la convierte double, el resultado será "13,421,773.5 / 134,217,728, más o menos 1 / 72,057,594,037,927,936 más o menos" - un nivel de precisión implícita lo cual está mal por un factor de más de 53 millones.

Aunque el estándar IEEE-744 requiere que las matemáticas de punto flotante se realicen como si cada número de punto flotante representara la cantidad numérica exacta precisamente en el centro de su rango, eso no debe suponerse que los valores de punto flotante realmente representan esos números exactos cantidades numéricas Más bien, el requisito de que se suponga que los valores están en el centro de sus rangos se deriva de tres hechos: (1) los cálculos deben realizarse como si los operandos tuvieran algunos valores precisos particulares; (2) los supuestos consistentes y documentados son más útiles que los inconsistentes o indocumentados; (3) si uno va a hacer una suposición consistente, ninguna otra suposición consistente es mejor que asumir que una cantidad representa el centro de su rango.

Por cierto, recuerdo que hace unos 25 años, a alguien se le ocurrió un paquete numérico para C que usaba "tipos de rango", cada uno de los cuales constaba de un par de flotadores de 128 bits; todos los cálculos se realizarían de tal manera que se calcule el valor mínimo y máximo posible para cada resultado. Si se realiza un cálculo iterativo largo y grande y se obtiene un valor de [12.53401391134 12.53902812673], se puede estar seguro de que si bien se perdieron muchos dígitos de precisión debido a errores de redondeo, el resultado aún podría expresarse razonablemente como 12.54 (y no fue así) t realmente 12.9 o 53.2). Me sorprende que no haya visto ningún soporte para estos tipos en ningún lenguaje convencional, especialmente porque parecería encajar bien con unidades matemáticas que pueden operar en múltiples valores en paralelo.

(*) En la práctica, a menudo es útil usar valores de doble precisión para mantener cálculos intermedios cuando se trabaja con números de precisión simple, por lo que tener que usar un tipo de letra para todas esas operaciones podría ser molesto. Los idiomas podrían ayudar al tener un tipo de "doble difuso", que realizaría cálculos como dobles, y podría emitirse libremente desde y hacia el sencillo; Esto sería especialmente útil si las funciones que toman parámetros de tipo doubley retorno doublepudieran marcarse de modo que generen automáticamente una sobrecarga que acepte y devuelva "doble difuso".

supercat
fuente
2

Si más lenguajes de programación tomaran una página de las bases de datos y permitieran a los desarrolladores especificar la longitud y precisión de sus tipos de datos numéricos, podrían reducir sustancialmente la probabilidad de errores relacionados con el punto flotante. Si un lenguaje permitiera a un desarrollador declarar una variable como Float (2), lo que indica que necesita un número de coma flotante con dos dígitos decimales de precisión, podría realizar operaciones matemáticas con mucha más seguridad. Si lo hiciera representando la variable como un número entero internamente y dividiéndola por 100 antes de exponer el valor, podría mejorar la velocidad al usar las rutas aritméticas de números enteros más rápidos. La semántica de un Float (2) también permitiría a los desarrolladores evitar la necesidad constante de redondear los datos antes de generarlos, ya que un Float (2) redondearía los datos inherentemente a dos puntos decimales.

Por supuesto, necesitaría permitir que un desarrollador solicite un valor de punto flotante de máxima precisión cuando el desarrollador necesita tener esa precisión. Y presentaría problemas en los que expresiones ligeramente diferentes de la misma operación matemática producen resultados potencialmente diferentes debido a operaciones de redondeo intermedias cuando los desarrolladores no tienen suficiente precisión en sus variables. Pero al menos en el mundo de las bases de datos, eso no parece ser un gran problema. La mayoría de las personas no están haciendo el tipo de cálculos científicos que requieren mucha precisión en los resultados intermedios.

Justin Cave
fuente
Especificar longitud y precisión haría muy poco que sea útil. Tener una base 10 de punto fijo sería útil para el procesamiento financiero, lo que eliminaría gran parte de la sorpresa que las personas obtienen del punto flotante.
David Thornley
@David: tal vez me falta algo, pero ¿en qué se diferencia un tipo de datos de base 10 de punto fijo de lo que propongo aquí? Un Float (2) en mi ejemplo tendría 2 dígitos decimales fijos y se redondearía automáticamente a la centésima más cercana, que es lo que probablemente usaría para cálculos financieros simples. Los cálculos más complejos requerirían que el desarrollador asigne una mayor cantidad de dígitos decimales.
Justin Cave
1
Lo que está recomendando es un tipo de datos de base 10 de punto fijo con precisión especificada por el programador. Estoy diciendo que la precisión especificada por el programador no tiene sentido en su mayoría, y solo conducirá a los tipos de errores que solía encontrar en los programas COBOL. (Por ejemplo, cuando cambia la precisión de las variables, es muy fácil pasar por alto una variable por la que se ejecuta el valor. Para otra, tomará mucho más pensar en el tamaño de resultado intermedio de lo que es bueno).
David Thornley
44
Float(2)No debería llamarse un " like" que usted propone Float, ya que no hay nada flotando aquí, ciertamente no es el "punto decimal".
Paŭlo Ebermann
1
  • los idiomas tienen soporte de tipo decimal; por supuesto, esto realmente no resuelve el problema, todavía no tiene una representación exacta y finita de, por ejemplo, ⅓;
  • algunos DB y frameworks tienen soporte de tipo Money, esto es básicamente almacenar el número de centavos como entero;
  • hay algunas bibliotecas para soporte de números racionales; eso resuelve el problema de ⅓, pero no resuelve el problema de, por ejemplo, √2;

Estos anteriores son aplicables en algunos casos, pero no son realmente una solución general para tratar con valores flotantes. La solución real es comprender el problema y aprender a lidiar con él. Si está utilizando cálculos de coma flotante, siempre debe verificar si sus algoritmos son numéricamente estables . Hay un campo enorme de matemática / informática que se relaciona con el problema. Se llama análisis numérico .

revs vartec
fuente
1

Como han señalado otras respuestas, la única forma real de evitar las trampas de coma flotante en el software financiero es no usarlo allí. Esto puede ser factible si proporciona una biblioteca bien diseñada dedicada a las matemáticas financieras .

Las funciones diseñadas para importar estimaciones de punto flotante deben etiquetarse claramente como tales y proporcionarse con parámetros apropiados para esa operación, por ejemplo:

Finance.importEstimate(float value, Finance roundingStep)

La única forma real de evitar dificultades de coma flotante en general es la educación: los programadores necesitan leer y comprender algo como Lo que todo programador debe saber sobre la aritmética de coma flotante .

Sin embargo, algunas cosas que podrían ayudar:

  • Respetaré a los que preguntan "¿por qué las pruebas de igualdad exactas para coma flotante son legales?"
  • En cambio, use una isNear()función.
  • Proporcione y fomente el uso de objetos acumuladores de punto flotante (que agregan secuencias de valores de punto flotante de manera más estable que simplemente agregarlos todos a una variable de punto flotante regular).
tormenta
fuente
-1

La mayoría de los programadores se sorprenderían de que COBOL acertara ... en la primera versión de COBOL no había coma flotante, solo decimal, y la tradición en COBOL continuó hasta hoy que lo primero que piensas al declarar un número es decimal. .. el punto flotante solo se usaría si realmente lo necesitaras. Cuando apareció C, por alguna razón, no había un tipo decimal primitivo, así que, en mi opinión, ahí es donde comenzaron todos los problemas.

JoelFan
fuente
1
C no tenía un tipo decimal porque no es primitivo, muy pocas computadoras tienen algún tipo de instrucciones decimales de hardware. Puede preguntar por qué BASIC y Pascal no lo tenían, ya que no fueron diseñados para ajustarse estrechamente al metal. COBOL y PL / I son los únicos idiomas que conozco de la época que tuvieron algo así.
David Thornley
3
@JoelFan: ¿cómo se escribe ⅓ en COBOL? Decimal no resuelve ningún problema, la base 10 es tan inexacta como la base 2.
vartec
2
Decimal resuelve el problema de representar exactamente dólares y centavos, lo cual es útil para un lenguaje "orientado a los negocios". Pero por lo demás, el decimal es inútil; tiene los mismos tipos de errores (por ejemplo, 1/3 * 3 = 0.99999999) mientras que es mucho más lento. Es por eso que no es el predeterminado en los idiomas que no fueron diseñados específicamente para la contabilidad.
dan04
1
Y FORTRAN, que es anterior a C en más de una década, tampoco tiene soporte decimal estándar.
dan04
1
@JoelFan: si tiene un valor trimestral y necesita un valor por mes, adivine qué tiene que multiplicar por ... no, no es 0.33, es ⅓.
vartec