Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Odejmowanie liczb zmiennoprzecinkowych błąd.

Ostatnio zmodyfikowano 2022-12-09 10:47
Autor Wiadomość
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.

C/C++
#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
P-179801
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.
P-179802
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?
P-179803
nanoant20
» 2022-12-08 22:19:50
C/C++
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
P-179804
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.

C/C++
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.
P-179805
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

C/C++
#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;
}

P-179806
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.
P-179807
« 1 »
  Strona 1 z 1