19 responses

  1. Nixz
    3 de febrero de 2006

    También sucede con:

    1000 – 999.9 – 0.1 = 2.27318164 × 10^(-14)

    y de ahí en adelante, se le pueden poner todas las cifras que queráis.

    Como curiosidad, la calculadora que viene con Ubuntu, ‘gcalctool’ (la que viene en el menú), da como resultado -0 (cero negativo). Y la otra calculadora que viene con Ubuntu, ‘xcalc’ (un poco más feílla) comete el mismo error que google… :S da exactamente:

    10 – 9.9 – 0.1 = -3,60822e-16

    En fin, ahí queda eso xD

    Saludos!

  2. Agnès
    3 de febrero de 2006

    ¡Qué CPI! 😛

  3. ^DiAmOnD^
    3 de febrero de 2006

    Yo escribi hace tiempo sobre el tema, pero los ejemplos que puse en mi post ya están arreglados.

    La verdad es que es muy curioso 😛

  4. cedila
    3 de febrero de 2006

    Es por esto que en un programa de computadora, uno no debe incluir comprobaciones de igualdad entre valores en coma flotante, como en este trocito de programa en C:

    float a = 0.1, b = 1.0, c = 0.9;

    if (a == b – c)
    puts(“¡Funciona! Qué raro”);
    else
    puts(“Ya me lo temía yo.”);

    la comprobación de igualdad

    if (a == b – c)

    fallará seguramente. Lo que se debe hacer es ponerlo de esta otra forma:

    if (fabs(a – (b – c)) < epsilon) donde fabs() es una función que devuelve el valor absoluto de un valor en coma flotante y epsilon es “un valor suficientemente pequeño”. Es una pena, pero es así. Los números que los computadores pueden manejar normalmente son sólo cierto subconjunto de los enteros y unos cuantos valores racionales, entre los que está el cero. Pero no se pueden representar cantidades con valor absoluto arbitrariamente pequeño ni arbitrariamente grande, y ciertos números racionales que en notación decimal tienen un número finito de cifras decimales, como 1/10, no tienen representación exacta en binario, en los circuitos del computador. Pasa como cuando queremos representar 1/3 en notación decimal, que hay que poner 0,33333… y en alguna parte hay que cortar, con el error de truncamiento correspondiente. Lo malo es cuando los errores de redondeo o truncamiento se propagan de cálculo en cálculo, tal vez amplificándose en cada nuevo ciclo de operaciones. Como los computadores pueden tener que hacer millones de operaciones dependientes una de otra para calcular un determinado resultado, hay veces que resulta muy difícil acotar el error. Con esas limitaciones aritméticas, la fiabilidad de los resultados dependerá de que los programadores sean conscientes de sus efectos y tomen medidas para paliarlos, pero esto, lamentablemente, no siempre sucede ¡Cualquiera se fía! :-)

  5. Ger
    3 de febrero de 2006

    A mi lo que me parece triste es que se permitan que el bendito Matlab tenga el mismo fallo … y hay veces, sobre todo en problemas en los que se involucran cantidades enormemente pequeñas, por ejemplo capacidades, donde este error de redondeo puede empezar a ser significativo

    Un saludo
    Grandioso estreno de sección

  6. Ger
    3 de febrero de 2006

    Se me ocurre un problema de magnetismo, donde puede aparecer valores de velocidades de la luz elevados a -2 (1.11e-17) ( eso en el mejor de los casos, con epsr = 1 y mur = 1). En este caso, el valor a hallar es menor que el redondeo, si no me equivoco

  7. Serlio
    4 de febrero de 2006

    No está directamente relacionado con la entrada, pero ayer descubrí casualmente que el buscador de MSN también soluciona ecuaciones (creo que es a través de Encarta), aunque me parece que sólo lo hace en su versión en inglés 😕

  8. Remo
    4 de febrero de 2006

    Efectivamente, Serlio:

    Encarta Answers also includes additional search functionality to help you with your homework or other everyday uses .
    • Definitions. Define a word or phrase, such as define lunar eclipse
    • Calculations. Calculate math problems, such as 2*5
    • Equations. Calculate math equations, such as 3x+4=10
    • Conversions. Get common conversions, such as what is 35 degrees Celsius in Fahrenheit

    Pero sólo resuelve ecuaciones polinómicas hata grado tres. Ni exponenciales, ni trigonométricas… Nada útil 😉

  9. hairanakh
    4 de febrero de 2006

    jop, Ger… pues yo con el Matlab sufro lo contrario. Como sólo sabe hacer cuentas con números de doble precisión (Double), cada vez que intento jugar con imágenes sufro mucho con la memoria.

    Por cierto, que para evitar esos problemas bastaría con limitar la precisión de las respuestas…

  10. Heimy
    4 de febrero de 2006

    Ger: El asunto es que no es un “fallo”. Es algo inherente a la representación de los números en el computador. Lo más que puedes hacer (y algunos lenguajes lo admiten, como Smalltalk), es utilizar tipos que representen números fraccionarios en lugar de decimales, y no convertirlos al valor real hasta el último momento. Pero esto es un poco ineficiente porque los cálculos en flotante los hace una unidad de cálculo del procesador, y las operaciones con fraccionarios los tienes que hacer tú “a mano”.

  11. Tronfi
    4 de febrero de 2006

    Acabo de hacer la prueba con Python 2.4 y pasa exactamente lo mismo :)

  12. josemi
    5 de febrero de 2006

    Recuerdo haber oido hablar de este tema alla por el año 84 u 85, una de las antiguas “muy interesante especial ordenadores”.

    En aquel momento, en la epoca del Commodore 64 y el Spectrum, cada modelo de BASIC manejaba los numeros como le daba la gana, aunque evidentemente todos tenian el problema.

    Lo peor es que parece que cada generacion tiene que descubrirlo de manera independiente :-)

  13. deibyz
    5 de febrero de 2006

    Ay… Qué recuerdos de esos primeros días de programador que ya dejé atrás…

    Como recuerdo volverme loco con los if()… Esas tardes a última hora llenándolo todo de sprintf()… Menos mal que desde hace mucho tiempo solo uso perl y un $#=”%.2f” lo arregla todo :)

    WN21@Deibyz /cygdrive/d$ perl -e ‘print ( 1 – .9 – .1 )’

    -2.77555756156289e-17

    WN21@Deibyz /cygdrive/d$ perl -e ‘$# = “%.2f”; print ( 1 – .9 – .1 )’
    0.00

    También recuerdo una práctica de C++ en la universidad en la que teníamos que definir una clase de float que almacenaba las cantidades en formato decimal (4bit por dígito si no recuerdo mal…). Lo dicho, ¡qué tiempos aquellos! Y qué recuerdos cada vez que un pogramador novel te viene completamente loco con un “bug” de este tipo… 😀

  14. PseudoGoN
    2 de noviembre de 2006

    Esto nos lo explicaron a fondo el primer año de carrera (informática). Como bien dicen, es una consecuencia de la representación en punto flotante (que es similar a la notación científica de toda la vida pero en binario). El caso es que cuando se producen estos errores al principio de los cálculos, al arrastrarlos se pueden formar errores importantes, por lo que la única solución posible es cambiar el orden de los mismos y dejar para el final las restas y las divisiones.

    Por cierto, las divisiones si que traen tela. Mientras que el resto de operaciones, aun siendo en punto flotante, se pueden segmentar en fases, consiguiendo así que, por ejemplo, varias multiplicaciones se hagan simultaneamente (cada multiplicación está en una de las fases en las que la operación se ha segmentado), la división no se segmenta, por lo que por cada división puedes perder decenas de ciclos de reloj. También es verdad que un motivo importante por el que no se divide en suboperaciones es porque se usa más bien poco y no merece la pena gastar más recursos en ella.

    Lo que no se es si en procesadores más avanzados, la han segmentado (por el momento estamos estudiando procesadores bastante sencillos). ¿Alguién lo sabe?

    saludos

    saludos

  15. javi
    9 de mayo de 2007

    Llevo tiempo siguiendo esta pagina, dando al botón de cpi al azar he llegado aquí, posiblemente esta entrada no sea ni si quiera conocida por la antigüedad de la última, (vamos, que esta entrada esta mas abandonada que el TAV de Cantabria) pero bueno, dejo lo siguiente:

    1 – 0x9 – 0.1 = -8.1

    Si no me equivoco, 0.9=0 y 0.1=0, por lo tanto 1-0-0=1, mis matemáticas creo que no fallan.

  16. Remo
    20 de mayo de 2007

    Javi: No entiendo bien tus cálculos. No sé si es que se ha estropeado algo al publicar, pero lo de 0.9=0 no me cuadra…

  17. javi
    2 de junio de 2007

    jaja, yo te lo explico, es una demostración más de que la calculadora no sabe realizar operaciones, por eso son operaciones al azar, y puse algo sencillo según se me ocurrió

  18. Charlie1
    11 de junio de 2007

    Es injusto abusar de la calculadora de google!! Para hacer multplicaciones debemos poner el asterico (*) en vez de la equis (x). Efectivamente javi, si escribes lo que tu pones en la calculadora de google da ese resultado (-8.1),pero google no entiende el simbolo “x” como multiplicacion. Si ponemos esto: 1-0*9-0.1 da el resultado correcto: 0.9. CPI LIFE FOREVER

  19. Jose Piñeiro
    18 de mayo de 2008

    @PseudoGoN

    Si lo que quieres es velocidad, la mejor forma de dividir es multiplicar.
    Por ejemplo, si en tu programa quries dividir entre 5, lo que debes hacer es multiplicar por 1/5 (es decir 0.2)
    Por tanto “a=b/5” es mucho mas lento que “a=b*0.2”

    El spectrum, que alguno lo mencinaba, cometia errores por otro motivo. Cuando tenemos poca potencia de calculo, multiplicar y dividir resulta sumamente lento. Para evitar este problema podemos hayar el loagritmos de los dos numeros, sumar los logaritmos y hyar el antilogaritmo. De esa manera hemos multiplicado.
    alog (log(x)+log(y)) = x*y
    alog (log(x)-log(y)) = x/y

    Obtener logaritmos y antilogaritmos es sencillo (solo hay que consultar una tabla). La suma y la resta son operaciones sencillas y rapidas.
    El unico problema es que nuestra precision queda limitada por la cantidad de decimales que tenga nuestra tabla de logaritmos.

    La mejor forma de dividir, ya que

Leave a Reply

 

 

 

Back to top
mobile desktop