Prerrequisitos: Errores de redondeo , Introducción a la representación de coma flotante El
algoritmo de suma de Kahan, también conocido como suma compensada y suma con el algoritmo de acarreo, se usa para minimizar la pérdida de importancia en el resultado total obtenido al agregar una secuencia de precisión finita Números de punto flotante. Esto se hace manteniendo una compensación de funcionamiento separada (una variable para acumular pequeños errores).
Motivo de la pérdida de importancia:
- Como sabemos, en el lenguaje Java tenemos dos tipos primitivos de punto flotante, float y double , con valores de formato de precisión simple de 32 bits y de precisión doble de 64 bits y operaciones especificadas por IEEE 754. Es decir, se representan en un formulario como:
SIGN FRACTION * 2EXP
- Por ejemplo, 0.15625 = (0.00101) 2 , que en formato de punto flotante se representa como: 1.01 * 2 -3 . Sin embargo, no todas las fracciones se pueden representar exactamente como una fracción de una potencia de dos. Por ejemplo, 0.1 = (0.000110011001100110011001100110011001100110011001100110011001… ) 2 y, por lo tanto, no se puede almacenar dentro de una variable de coma flotante.
- Por lo tanto, el error de coma flotante/pérdida de significado se refiere a cuando un número que no se puede almacenar tal como está en la representación de coma flotante de IEEE y se realiza una operación aritmética repetitiva en él. Esto conduce a algún valor inesperado y la diferencia entre el valor esperado y el obtenido es el error.
A continuación se muestra una implementación que simula el error de significancia:
C++
// C++ program to illustrate the // floating-point error #include<bits/stdc++.h> using namespace std; double floatError(double no) { double sum = 0.0; for(int i = 0; i < 10; i++) { sum = sum + no; } return sum; } // Driver code int main() { cout << setprecision(16); cout << floatError(0.1); } // This code is contributed by rutvik_56
Java
// Java program to illustrate the // floating-point error public class GFG { public static double floatError(double no) { double sum = 0.0; for (int i = 0; i < 10; i++) { sum = sum + no; } return sum; } public static void main(String[] args) { System.out.println(floatError(0.1)); } }
Python3
# Python3 program to illustrate the # floating-point error def floatError(no): sum = 0.0 for i in range(10): sum = sum + no return sum if __name__ == '__main__': print(floatError(0.1)) # This code is contributed by mohit kumar 29
Javascript
<script> // Javascript program to illustrate the // floating-point error function floatError(no) { let sum = 0.0; for (let i = 0; i < 10; i++) { sum = sum + no; } return sum; } document.write(floatError(0.1)); // This code is contributed by patel2127 </script>
0.9999999999999999
Nota: El valor esperado para la implementación anterior es 1,0 pero el valor devuelto es 0,9999999999999999. Por lo tanto, en este artículo, se analiza un método para reducir este error utilizando el algoritmo de suma de Kahan.
Algoritmo de suma de Kahan: la idea del algoritmo de suma de Kahan es compensar el error de punto flotante manteniendo una variable separada para almacenar los errores de tiempo de ejecución a medida que se realizan las operaciones aritméticas. Esto se puede visualizar mediante el siguiente pseudocódigo:
function KahanSum(input) var sum = 0.0 var c = 0.0 for i = 1 to input.length do var y = input[i] - c var t = sum + y c = (t - sum) - y sum = t next i return sum
En el pseudocódigo anterior, algebraicamente, la variable c en la que se almacena el error siempre es 0. Sin embargo, cuando hay una pérdida de significado, almacena el error en ella.
A continuación se muestra la implementación del enfoque anterior:
C++
// C++ program to illustrate the // Kahan summation algorithm #include <bits/stdc++.h> using namespace std; // Function to implement the Kahan // summation algorithm double kahanSum(vector<double> &fa) { double sum = 0.0; // Variable to store the error double c = 0.0; // Loop to iterate over the array for(double f : fa) { double y = f - c; double t = sum + y; // Algebraically, c is always 0 // when t is replaced by its // value from the above expression. // But, when there is a loss, // the higher-order y is cancelled // out by subtracting y from c and // all that remains is the // lower-order error in c c = (t - sum) - y; sum = t; } return sum; } // Function to implement the sum // of an array double sum(vector<double> &fa) { double sum = 0.0; // Loop to find the sum of the array for(double f : fa) { sum = sum + f; } return sum; } // Driver code int main() { vector<double> no(10); for(int i = 0; i < 10; i++) { no[i] = 0.1; } // Comparing the results cout << setprecision(16); cout << "Normal sum: " << sum(no) << " \n"; cout << "Kahan sum: " << kahanSum(no); } // This code is contributed by ajaykr00kj
Java
// Java program to illustrate the // Kahan summation algorithm public class GFG { // Function to implement the Kahan // summation algorithm private static double kahanSum(double... fa) { double sum = 0.0; // Variable to store the error double c = 0.0; // Loop to iterate over the array for (double f : fa) { double y = f - c; double t = sum + y; // Algebraically, c is always 0 // when t is replaced by its // value from the above expression. // But, when there is a loss, // the higher-order y is cancelled // out by subtracting y from c and // all that remains is the // lower-order error in c c = (t - sum) - y; sum = t; } return sum; } // Function to implement the sum // of an array private static double sum(double... fa) { double sum = 0.0; // Loop to find the sum of the array for (double f : fa) { sum = sum + f; } return sum; } // Driver code public static void main(String[] args) { double[] no = new double[10]; for (int i = 0; i < no.length; i++) { no[i] = 0.1; } // Comparing the results System.out.println("Normal sum: " + sum(no)); System.out.println("Kahan sum: " + kahanSum(no)); } }
Javascript
<script> // Javascript program to illustrate the // Kahan summation algorithm // Function to implement the Kahan // summation algorithm function kahanSum(fa) { let sum = 0.0; // Variable to store the error let c = 0.0; // Loop to iterate over the array for(let f = 0; f < fa.length; f++) { let y = fa[f] - c; let t = sum + y; // Algebraically, c is always 0 // when t is replaced by its // value from the above expression. // But, when there is a loss, // the higher-order y is cancelled // out by subtracting y from c and // all that remains is the // lower-order error in c c = (t - sum) - y; sum = t; } return sum; } // Function to implement the sum // of an array function sum(fa) { let sum = 0.0; // Loop to find the sum of the array for(let f = 0; f < fa.length; f++) { sum = sum + fa[f]; } return sum; } // Driver code let no = new Array(10); for(let i = 0; i < no.length; i++) { no[i] = 0.1; } // Comparing the results document.write("Normal sum: " + sum(no) + "<br>"); document.write("Kahan sum: " + kahanSum(no).toFixed(1) + "<br>"); // This code is contributed by unknown2108 </script>
Python3
# Python3 program to illustrate the # Kahan summation algorithm # Function to implement the Kahan # summation algorithm def kahanSum(fa): sum = 0.0 # Variable to store the error c = 0.0 # Loop to iterate over the array for f in fa: y = f - c t = sum + y # Algebraically, c is always 0 # when t is replaced by its # value from the above expression. # But, when there is a loss, # the higher-order y is cancelled # out by subtracting y from c and # all that remains is the # lower-order error in c c = (t - sum) - y sum = t return sum # Driver code if __name__ == "__main__": no = [0.0] * 10 for i in range(10): no[i] = 0.1 # Comparing the results print("Normal sum: ", sum(no)) print("Kahan sum: ", kahanSum(no))
Normal sum: 0.9999999999999999 Kahan sum: 1.0
Complejidad temporal: O(N), donde N es la longitud de la lista.
Espacio Auxiliar: O(1)
Publicación traducida automáticamente
Artículo escrito por Bishal Kumar Dubey y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA