Elutka89 Temat założony przez niniejszego użytkownika |
[C++] Suma elementów tablicy - liczby rzeczywiste » 2013-07-26 08:55:38 Witam,
nie mogę znaleźć błędu we fragmencie programu, który napisałam. Chodzi o obliczenie sumy elementów tablicy, do której dane wczytywane są z klawiatury. Przy wybranych danych w ogóle nie wchodzi do pętli, pomimo iż suma jest różna od 1. Czasem działa, a czasem wchodzi do pętli, pomimo iż wypisujemy, że suma jest równa 1, czyli warunek spełniony, i do pętli while nie powinien wchodzić... Proszę o pomoc. Oto fragment programu:
#include <iomanip> #include <iostream> #include <conio.h> #include <cstdlib> #include <cstdio> #include <stdio.h> #include <string> #include <fstream> #include <math.h> using namespace std;
char t_atr[ 10 ][ 15 ]; int i, j; float suma = 0; float k[ 20 ];
int main( int argc, char * argv[] ) { cout << "\n\nPodaj udzialy wagowe poszczegolnych atrybutow: "; for( i = 0; i < m; i++ ) { cout << "\n" << t_atr[ i ] << " "; cin >> k[ i ]; suma = suma + k[ i ]; } cout << "Suma wynosi: " << suma << "\n"; while( suma != 1 ) { cout << "\nSuma udzialow wagowych musi byc rowna 1. \nU Ciebie wynosi: " << suma << "\n\nWpisz dane jeszcze raz:"; suma = 0; for( i = 0; i < m; i++ ) { cout << "\n" << t_atr[ i ] << " "; cin >> k[ i ]; suma = suma + k[ i ]; } } return 0; } |
|
Rafi |
» 2013-07-26 09:24:25 Nie rozumiem, po co tworzysz tablicę dwuwymiarową - w programie jej nie używasz. Nie możesz też dodawać do zmiennej typu float zmiennej char. Btw. po co ci tyle bibliotek? ;) |
|
Elutka89 Temat założony przez niniejszego użytkownika |
» 2013-07-26 11:17:09 Z tablicy typu char tylko wypisuję nazwy atrybutów... I ona jest dwuwymiarowa. Ale tablicę "k[20]" chciałabym zsumować, i to właśnie mi nie wychodzi. Biblioteki są po to, że program jest dużo dłuższy, to tylko niewielki jego fragment, z którym mam problem. Dopisałam jednak wczytywanie wartości do tablicy t_atr żeby można było go skompilować. Przykładowo jeśli wpisuję jako liczbę atrybutów m=4, i podaje następujące dane, jako udziały wagowe: 0.11, 0.78, 0.03, 0.08. To program nie działa poprawnie. #include <iomanip> #include <iostream> #include <conio.h> #include <stdio.h> #include <string>
using namespace std;
char t_atr[ 10 ][ 15 ]; int i, j, n, m; float suma = 0; float k[ 20 ];
int main( int argc, char * argv[] ) { cout << "liczba atrybutow: "; cin >> m; for( i = 0; i < m; i++ ) { cout << "\nAtrybut " << i + 1 << " "; cin >> t_atr[ i ]; } cout << "\n\nPodaj udzialy wagowe poszczegolnych atrybutow: "; for( i = 0; i < m; i++ ) { cout << "\n" << t_atr[ i ] << " "; cin >> k[ i ]; suma = suma + k[ i ]; } cout << "Suma wynosi: " << suma << "\n"; while( suma != 1 ) { cout << "\nSuma udzialow wagowych musi byc rowna 1. \nU Ciebie wynosi: " << suma << "\n\nWpisz dane jeszcze raz:"; suma = 0; for( i = 0; i < m; i++ ) { cout << "\n" << t_atr[ i ] << " "; cin >> k[ i ]; suma = suma + k[ i ]; } } return 0; }
|
|
Monika90 |
» 2013-07-26 12:20:26 Zwróć uwagę, że suma liczb 0.11, 0.78, 0.03, 0.08 jest równa 0.99999994039535522. Jeżeli zamiast float użyjesz double, to będzie trochę lepiej, ale tylko trochę... |
|
Elutka89 Temat założony przez niniejszego użytkownika |
» 2013-07-26 12:38:32 Skąd się bierze taki wynik tej sumy? Zmieniłam na double, teraz działa. Ale co zrobić, aby przy dowolnych liczbach, które podawane będą z dokładnością (co najwyżej) do drugiego miejsca po przecinku program działał poprawnie? Program wypisuje też wartość sumy, i pisze, że jest ona równa 1. |
|
Monika90 |
» 2013-07-26 13:00:05 | Skąd się bierze taki wynik tej sumy? |
W Twojej implementacji liczby zmiennoprzecinkowe używają systemu dwójkowego, a istnieją takie liczby rzeczywiste, np. 0.03, które mają nieskończone rozwinięcie binarne. W związku z tym muszą być obcięte lub zaokrąglone, żeby się zmieściły w skończonej precyzji jaka jest dostępna. Więc wpisujesz 0.03, ale wartośc zmiennej będzie trochę większa lub mniejsza niż 0.03, więc suma też będzie trochę mniejsza lub większa niż 1. | Program wypisuje też wartość sumy, i pisze, że jest ona równa 1. |
Bo przy wyświetlaniu wynik jest zaokrąglany. Użyj cout.precision( 16 ); , a poznasz straszną prawdę. | Ale co zrobić, aby przy dowolnych liczbach, które podawane będą z dokładnością (co najwyżej) do drugiego miejsca po przecinku program działał poprawnie? |
Nie wiem. Zależy, co w ogóle chcesz obliczać i po co? |
|
Elutka89 Temat założony przez niniejszego użytkownika |
» 2013-07-26 13:40:56 Hmm... Zrobiłam wyświetlanie do 16 miejsc, ale u mnie on nie wyświetla tej liczby, którą podałaś, ale jedynkę z samymi zerami. Teraz na prawdę nie wiem, dlaczego występuje taka różnica, skoro nic więcej nie zmieniłam, i podaję wciąż te same 4 liczby. Pytałaś, co chcę zrobić. Otóż chodzi mi o to, żeby użytkownik programu wpisał z klawiatury m wartości z dokładnością do dwóch miejsc po przecinku. Dalsza część programu nie będzie dawała wiarygodnego wyniku, jeśli suma elementów wpisanych do tablicy k nie będzie równa 100%. Dlatego też zrobiłam pętle while, żeby użytkownik wpisał wartości, które (przy założeniu zaokrąglenia do 1 procenta) dadzą 100%. |
|
jankowalski25 |
» 2013-07-26 21:34:22 | Hmm... Zrobiłam wyświetlanie do 16 miejsc, ale u mnie on nie wyświetla tej liczby, którą podałaś, ale jedynkę z samymi zerami. |
To zależy od użytego kompilatora i jego implementacji liczb zmiennoprzecinkowych. | Ale co zrobić, aby przy dowolnych liczbach, które podawane będą z dokładnością (co najwyżej) do drugiego miejsca po przecinku program działał poprawnie? |
Jeśli wynik obliczany przy użyciu typów wbudowanych nie będzie wystarczający, możesz wczytać dane do zmiennych przechowujących tekst i samodzielnie zaimplementować pisemne dodawanie liczb zapisanych w postaci tekstu. |
|
| « 1 » 2 |