Odejmowanie liczb zmiennoprzecinkowych błąd.
Ostatnio zmodyfikowano 2022-12-09 10:47
itab Temat założony przez niniejszego użytkownika |
Odejmowanie liczb zmiennoprzecinkowych błąd. » 2022-12-08 14:46:37 Cześć, mam błąd z prostą funkcją, gdzie wynikiem powinno być zero, a nie jest :) Szukałem po internecie odpowiedzi ale jej nie znalazłem. #include <iostream>
using namespace std;
void x( double a, double b, double c ) { double temp = a - b - c; cout << temp << endl; }
int main() { double a = 3.33; double b = 2.22; double c = 1.11; x( a, b, c ); return 0; }
-2.22045e-16
|
|
pekfos |
» 2022-12-08 19:54:09 To jest poprawne zachowanie. Te ułamki mają nieskończone rozwinięcie w systemie dwójkowym, a precyzja double jest ograniczona. |
|
itab Temat założony przez niniejszego użytkownika |
» 2022-12-08 20:52:47 W takim razie jak to rowiązać aby wynik był prawidłowy? |
|
nanoant20 |
» 2022-12-08 22:19:50 void x( double a, double b, double c ) { double val = std::numeric_limits < double >::epsilon(); double temp = abs( a - b - c ) < val; cout << temp << endl; }
rozwiązanie, które tutaj podałem jest błędne, w następnym poście poprawiłem |
|
pekfos |
» 2022-12-08 22:39:32 W takim razie jak to rowiązać aby wynik był prawidłowy? Nie używaj liczb zmiennoprzecinkowych. Można reprezentować liczby ułamkowe jako wynik dzielenia dwóch liczb całkowitych, ale to będzie działać tylko dla liczb wymiernych, nie ma na to gotowego rozwiązania w bibliotece standardowej i dalej nie unikasz w 100% problemu nieskończenie długich liczb. W tym przypadku najprościej pomnożyć wszystko przez 100 i podzielić wynik przez 100 po wykonaniu operacji. Przy czym pomnożyć przez 100 ręcznie. 3.33 w kodzie jest już z błędem. void x( double a, double b, double c ) { double val = std::numeric_limits < double >::epsilon(); double temp = abs( a - b - c ) < val; cout << temp << endl; } Chodziło o uzyskanie wyniku 0, nie przyrównanie wyniku do zera. Zabawne że ten kod faktycznie wypisuje 0, bo wynik obliczeń ma zbyt duży błąd dla tej tolerancji. |
|
nanoant20 |
» 2022-12-08 22:57:54 rozwiązanie które zaproponowałem powyżej jest błędne teraz dopiero to zauważyłem, jak zacząłem testować // edit #include <iostream> #include <limits> #include <cmath>
using namespace std;
double aproksymacja( double value ) { return( roundf( value * 100 ) / 100 ); }
double solution( double a, double b, double c ) { return aproksymacja( a - b - c ); }
int main() { double a = 3.33; double b = 2.22; double c = 1.11; double result = solution( a, b, c ); cout << result << "\n"; return 0; }
|
|
itab Temat założony przez niniejszego użytkownika |
» 2022-12-09 10:47:17 O kurka wodna, nie spodziewałem się, że to będzie takie skomplikowane. Dziękuję ślicznie za pomoc. |
|
« 1 » |