Por qué los valores de punto flotante no representan el valor exacto

Los números de punto flotante sirven como aproximaciones aproximadas de números reales matemáticos. No representan el valor exacto. Por esta razón, comparamos los resultados aritméticos de variables flotantes con un valor de tolerancia mínimo. 
Ejemplo:

C++

// C++ program to illustrate the
// floating point values
#include <bits/stdc++.h>
using namespace std;
 
// Driver Code
int main()
{
    double num1 = 10000.29;
    double num2 = 10000.2;
 
    // Output should be 0.0900000000
    cout << std::setprecision(15)
         << (num1 - num2);
    return 0;
}

Java

// Java program to illustrate the
// floating point values
import java.text.DecimalFormat;
 
class GFG{
 
// Driver Code
public static void main(String[] args)
{
    double num1 = 10000.29;
    double num2 = 10000.2;
 
    // Output should be 0.0900000000
    DecimalFormat df = new DecimalFormat(
        "#.################");
         
    System.out.println(df.format(num1 - num2));
}
}
 
// This code is contributed by 29AjayKumar

Python3

# Python3 program to illustrate
# the floating povalues
# Driver Code
if __name__ == '__main__':
    num1 = 10000.29;
    num2 = 10000.2;
 
    # Output should be 0.0900000000
    print ("{0:.10f}".format(num1 - num2));
 
# This code is contributed by Rajput-Ji

C#

// C# program to illustrate the
// floating point values
using System;
 
class GFG{
 
// Driver Code
public static void Main(String[] args)
{
    double num1 = 10000.29;
    double num2 = 10000.2;
 
    // Output should be 0.0900000000
    Console.WriteLine(
        string.Format("{0:F15}",
        Decimal.Parse((num1 - num2).ToString())));
}
}
 
// This code is contributed by 29AjayKumar
Producción: 

0.0900000000001455


Explicación: 
La salida esperada es 0.09 como salida. Pero, la salida no es 0.09. Para entender esto, primero debe saber cómo funciona una computadora con valores flotantes. Cuando se inicializa una variable flotante, la computadora la trata como un valor exponencial y asigna 4 bytes (32 bits) de memoria donde la parte de la mantisa ocupa 24 bits , la parte del exponente ocupa 7 bits y el 1 bit restante se usa para indicar el signo. 
Para el tipo doble, la computadora hace lo mismo pero asigna una memoria más grande en comparación con el tipo flotante. En el sistema decimal, cada posición de (izquierda a derecha) en la parte fraccionaria es una décima parte de la posición a su izquierda. Si nos movemos de derecha a izquierda, cada posición es 10 veces la posición a su derecha. 
En un sistema binario, el factor es dos como se muestra en la tabla:
 

dieciséis 8 4 2 1 . \frac{1}{2} \frac{1}{4} \frac{1}{8}
2^4 2^3 2^2 2^1 2^0 . 2^{-1} 2^{-2} 2^{-3}

Para simplificar las cosas, pensemos en un tipo mítico llamado float pequeño (vea la imagen de arriba) que consta de solo 5 bits, muy pequeño en comparación con float y double. Los tres primeros bits del tipo float pequeño representarán la mantisa, los últimos 2 bits representarán la parte del exponente. En aras de la simplicidad, no pensamos en el signo. Entonces, la parte de la mantisa solo puede tener 8 valores posibles y la parte del exponente solo puede tener 4 valores posibles. Vea las tablas a continuación:
 

patrón de bits valor binario valor decimal
000 (0.000) 2 0.000
001 (0.001) 2 0.125
010 (0.010) 2 0.250
011 (0.011) 2 0.375
100 (0.100) 2 0.500
101 (0.101) 2 0.625
110 (0.110) 2 0.750
111 (0.111) 2 0.875
patrón binario valor binario valor decimal
00 (00) 2 1
01 (01) 2 2
10 (10) 2 4
11 (11) 2 8

Entonces, una combinación de mantisa y parte de exponente puede ser 11100 donde los dos bits más a la izquierda representan la parte de exponente y los tres bits restantes representan la parte de mantisa. El valor se calcula como: 
 

(1\times 2^{-1}+1\times 2^{-2}+1\times 2^{-2})\times 2^{(0\times 2^1+0\times 2^0)} = 0.875

De las dos tablas, podemos decir fácilmente que un pequeño flotador puede contener solo 32 números y el rango del tipo mítico es de 0 a 7. El rango no es igualmente denso. Si observa la siguiente imagen detenidamente, verá que la mayoría de los valores se encuentran entre 0 y 1. Cuanto más se mueva de derecha a izquierda, más dispersos serán los números.
 

El flotador pequeño no puede representar 1.3, 2.4, 5.6, etc. En ese caso, el flotador pequeño los aproxima. No puede representar números mayores de 7. Además muchas combinaciones representan el mismo valor. Por ejemplo: 00000, 00001, 00010, 00011 representan el mismo valor decimal, es decir, (0,000). Doce de las 32 combinaciones son redundantes. 
Si aumentamos el número de bits asignados para el pequeño valor flotante, la parte más densa aumentará. Como los valores flotantes reservan 32 bits, el valor flotante puede representar más números en comparación con el valor flotante pequeño. Pero se pueden observar algunos problemas con valores flotantes y valores dobles. No hay camino para superar esto. Las computadoras con memoria infinita y un preprocesador rápido solo pueden calcular valores flotantes o dobles exactos, lo cual es una fantasía para nosotros.
 

Publicación traducida automáticamente

Artículo escrito por samufo y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *