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 |