2011-01-05 12 views
5

que he tenido este problema en mi mente las lastfew día, y estoy luchando por la frase mi pregunta. Sin embargo, creo que he encontrado lo que quiero saber.Cuál es el beneficio de aceptar la inexactitud de punto flotante en C#

¿Por qué C# acepta la imprecisión mediante el uso de puntos flotantes para almacenar datos? ¿Y cuál es el beneficio de usarlo sobre otros métodos?

Por ejemplo, Math.Pow(Math.Sqrt(2),2) no es exacto en C#. Hay lenguajes de programación que pueden calcularlo exactamente (por ejemplo, Mathematica).

Un argumento que podía pensar es que el cálculo de exactamente es mucho más lento que acaba de hacer frente a la falta de exactitud, pero Mathematica & Matlab se utilizan para calcular los problemas científicos gigantescas, por lo que me resulta difícil de creer que estas lenguas son muy significativamente más lento que C#.

Entonces, ¿por qué es entonces?

PD: Lo siento por que el correo basura con estas preguntas, todo lo que ha sido de gran ayuda

+0

MatLab se ejecuta en un entorno limitado de Java. Si no cree que MatLab es más lento, intente crear un programa en tiempo real en MatLab. He estado allí, hecho eso, no es divertido ... :-) –

+0

Bien, ¿pero Wolfram Mathematica entonces? No pude encontrar puntos de referencia en Internet en comparación con C# –

+1

El [CAS] (http://en.wikipedia.org/wiki/Computer_algebra_system) integrado en la calculadora TI-89 que prácticamente me ayudó a superar los cursos de matemáticas de la universidad. los pantalones fuera de la funcionalidad matemática incorporada en .NET Framework, también. El hecho es que están diseñados para casos de uso totalmente diferentes. –

Respuesta

32

¿Por qué C# acepta la imprecisión mediante el uso de puntos flotantes para almacenar datos?

"C#" no acepta la compensación del rendimiento por encima de la precisión; los usuarios aceptan, o no, eso.

C# tiene tres tipos de punto flotante - flotante, doble y decimal - porque estos tres tipos satisfacen la gran mayoría de las necesidades de los programadores del mundo real.

float y double son buenos para cálculos "científicos" donde una respuesta correcta a tres o cuatro decimales siempre es lo suficientemente cerca, porque esa es la precisión con la que llegó la medida original. Supongamos que divide 10.00 por 3 y obtiene 3.333333333333. Dado que la medición original probablemente solo tenía una precisión de 0.01, el hecho de que el resultado calculado esté desactivado en menos de 0.0000000000004 es irrelevante. En cálculos científicos, no está representando cantidades conocidas para ser exactas. La imprecisión en el decimoquinto lugar decimal es irrelevante si el valor de medición original solo era preciso al segundo decimal.

Esto, por supuesto, no es cierto para los cálculos financieros. Los operandos para un cálculo financiero suelen ser precisos con dos decimales y representan las cantidades exactas. El decimal es bueno para cálculos "financieros" porque los resultados de la operación decimal son exacta, siempre que todas las entradas y salidas se puedan representar exactamente como decimales (y todas están en un rango razonable). Los decimales todavía tienen errores de redondeo, por supuesto, pero las operaciones que son exactas son precisamente aquellas que es probable que quieras ser exacto al hacer los cálculos financieros.

¿Y cuál es la ventaja de usarlo sobre otros métodos?

Debe indicar qué otros métodos le gustaría comparar. Hay muchas técnicas diferentes para realizar cálculos en computadoras.

Por ejemplo, Math.Pow (Math.Sqrt (2), 2) no es exacto en C#. Hay lenguajes de programación que pueden calcularlo exactamente (por ejemplo, Mathematica).

Seamos claros en este punto; Mathematica no "calcula" la raíz 2 exactamente; el número es irracional, por lo que no se puede calcular exactamente en ninguna cantidad finita de almacenamiento. En cambio, lo que hace la matemática es que representa los números como objetos que describen cómo se produjo el número. Si dices "dame la raíz cuadrada de dos", entonces Mathematica esencialmente asigna un objeto que significa "la aplicación del operador de raíz cuadrada al número exacto 2". Si luego lo cuadras, tiene una lógica de propósito especial que dice "si cuadras algo que era la raíz cuadrada de otra cosa, devuelve el valor original". Mathematica también tiene objetos que representan varios números especiales, como pi o e, y un enorme conjunto de reglas sobre cómo se combinan varias manipulaciones de esos números.

Básicamente, es un sistema simbólico; manipula los números de la misma manera que las personas cuando hacen matemáticas de lápiz y papel. La mayoría de los programas de computadora manipulan números como una calculadora: realice el cálculo de inmediato y complételo. Si eso no es aceptable, entonces debes apegarte a un sistema simbólico.

Un argumento que podía pensar es que el cálculo de exactamente es mucho más lento que acaba de hacer frente a la falta de exactitud, pero Mathematica & Matlab se utilizan para calcular los problemas científicos gigantescas, por lo que me resulta difícil de creer que estas lenguas son realmente significativamente más lento que C#.

No es que sean más lentos, aunque la multiplicación de puntos flotantes realmente es increíblemente rápida en hardware moderno. Es que el motor de cálculo simbólico es inmensamente complejo. Codifica todas las reglas de las matemáticas básicas, ¡y hay muchas de esas reglas! C# no pretende ser un motor de cálculo simbólico de nivel profesional, sino un lenguaje de programación de propósito general.

+2

+1 excelente respuesta –

+1

Un montón de calculadoras científicas "hacen trampa" al mantener un par de dígitos extra detrás de las escenas y usarlos para redondear en lugar de mostrarlos. Considera Google, que felizmente hace ['Sqrt (2) ** 2'] (http://www.google.com/search?q=sqrt%282%29%2A%2A2) corregir ... pero ¿qué pasa con [ 'sqrt (1.999999999) ** 2'] (http://www.google.com/search?q=sqrt%281.999999999%29%2A%2A2)? – Brian

+2

+1 No puedo decirle lo refrescante que es ver a un programador que realmente entiende y aprecia cifras significativas. Pero esta es una respuesta completamente fantástica por muchas razones. –

0

C# y la mayoría de todos los otros idiomas (excepto los específicos, como Matlab) almacenar números de punto flotante como campos de tamaño fijo (6 u 8 bytes), lo que genera inexactitudes.

+0

Lo sé, pero ¿por qué usa números de coma flotante, si hay otras formas? –

+0

@Timo ¿De qué otras maneras, si usa campos de tamaño fijo? La gran mayoría de la informática, a excepción de la informática científica, no necesita precisión infinita y puede aceptar algún nivel de inexactitud. –

+0

Debido a la velocidad de procesamiento y la eficiencia de almacenamiento. Esa es la razón principal. La mayoría de los programas no necesitan precisión en 10 símbolos después del punto. –

12

Una palabra: rendimiento. La aritmética de coma flotante se implementa típicamente en hardware y es de varios órdenes de magnitud más rápida que otros enfoques.

Además, su ejemplo de MATLAB es falso. MATLAB utiliza aritmética de coma flotante de doble precisión al igual que C#.

+1

+1 No solo el rendimiento, sino el hecho de que la compensación valor-rendimiento no vale la pena en el 99% de los casos. La única vez que necesita los altos niveles de precisión que asume su pregunta es si está haciendo cálculos matemáticos o de ingeniería especializados. Y ya hay software para eso. –

+0

Bien, he eliminado el ejemplo de MATLAB. No estaba muy seguro, pero la matemática puede hacerlo bien? –

+3

@Timo Hay una diferencia entre la computación numérica y simbólica. La mayoría de los problemas científicos y de ingeniería del mundo real están mejor atendidos por algoritmos numéricos y para ellos la aritmética de punto flotante es lo mejor. Esto es esencialmente reformular lo que dice @Cody Gray. –

0

No creo que sea un problema de C#. C# es un lenguaje de propósito general y le proporciona tipos de datos básicos para jugar. Si no estás contento con ellos, siempre puedes crear el tuyo propio.

Además C# no es el que acepta inexactitudes. El programador lo hace. Para un gran conjunto de problemas, la inexactitud es aceptable. Float no debe usarse cuando se espera un resultado exacto, pero esta es una decisión para el programador y no para el diseñador del lenguaje.

0

Una razón es que los números y formatos de números son inequívocos y universales. Sí, hay errores de redondeo, pero son constantes y predecibles. Intentar configurar un formato general para cualquier problema algorítmico no es trivial.

2

Para la mayoría de los problemas de programación, la inexactitud no es un problema y los tipos de datos float (o double) son lo suficientemente buenos. Hace muchos años, no existían los "valores de punto flotante" y el software tenía que almacenar dichos valores como dos enteros. Y el rendimiento fue un problema (sin mencionar errores de programación, y escenarios wtf) a partir de funciones de cálculo de coma flotante hechas a medida). Por lo tanto, se diseñó una convención y poco después las computadoras se equiparon con FPU s.

Ahora, cuando usar la FPU para hacer cálculos o usar otras librerías/programas matemáticos (como Mathematica) depende del problema. Por ejemplo, el cálculo de vértices en un entorno 3D prefiere el rendimiento sobre la precisión. Pero el software de contabilidad es diferente. En ese aspecto, ambos problemas difieren; un software de contabilidad no necesitará calcular números complejos millones de veces por segundo :) (edit: ¡o si lo hace, algunos equipos muy caros probablemente también sean parte de la ecuación!)

Si sabe que se va a realizar Math.pow (Math.sqrt (2), 2), entonces usted debe reconsiderar la forma en que almacena dos valores (como ellos volver a calcular cada vez). Esto no es un problema con el lenguaje de programación, sino más bien un problema conceptual.

3

¿Por qué C# acepta la imprecisión mediante el uso de puntos flotantes para almacenar datos?

De esta manera, el soporte de punto flotante puede asignar a la manera de hardware es compatible con puntos flotantes, es decir - es la más o menos la única manera de tomar ventaja de las operaciones de punto flotante en hardware, que es mucho más rápido que una solución de software. El inconveniente es que el hardware representa los puntos flotantes con un número finito de bits, lo que conduce a la inexactitud (tenga en cuenta que la inexactitud está bien definida).

Otras formas de representar los valores de punto flotante necesitan una solución de software, es mucho más lenta y requiere más espacio. "Cualquiera" puede implementar eso con lo que está disponible en C#, incluido el soporte de punto flotante nativo para el hardware disponible sería bastante difícil para "cualquiera" si esto no fuera compatible con el idioma/CLR.

0

Hay un poco de una explicación here para Mathematica

La versión corta es para el día a día regular de matemáticas de punto flotante, el hardware puede hacer rápidamente con una cantidad conocida de inexactitud. Entonces, si su cálculo no se basa en ser más preciso, hágalo de la manera más rápida.

Si necesita la precisión, el programador debe escribir el algoritmo con el grado de precisión requerido. Que será más lento.

Cuestiones relacionadas