• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Trójmian kwadratowy - napisz program

Object Storage Arubacloud
0 głosów
3,414 wizyt
pytanie zadane 7 października 2018 w C i C++ przez Vitall Początkujący (400 p.)

Cześć,

zadanie jest proste:

Napisać program rozwiązujący równanie kwadratowe (postaci ax2+bx+c=0) o podanych przez użytkownika  współczynnikach całkowitych (ja sobie zrobiłem rzeczywiste, bo int-y też na tym chodzą, a mam większe spektrum możliwości).

Oto moje rozwiązanie - wg mnie działa, prosiłbym o uwagi, jeśli można coś zrobić bardziej elegancko, profesjonalnie i jeśli coś jest źle, to o wytknięcie błędu. Swoją drogą jak się robi liczby zespolone w C++?
[jestem na początku przygodny z C++].

Aha, jak wychodzi piewiastek = 0, to wyświetla -0, ktoś z Was wie jak sobie z tym poradzić?

#include<iostream>
#include<cmath>
using namespace std;

int main()
{
    
    double a, b, c, x, delta, x1, x2;
    cout << "Podaj wspolczynniki trojmianu kwadratowego \na: ";
    cin >> a;
    cout <<"b: "; 
    cin >> b;
    cout << "c: ";
    cin >> c;
    
    if (a == 0)
        cout << "To nie jest rownanie kwadratowe, tylko liniowe !!!";
    else
        {
            delta = pow(b,2) - 4*a*c;
            if (delta > 0)
                {
                    x1 = (-b - sqrt(delta)) / 2*a;
                    x2 = (-b + sqrt(delta)) / 2*a;
                    cout << "Delta: " << delta << endl <<
                    "x1: " << x1 << " oraz x2: " << x2;
                    
                }
            else if (delta == 0)
                {
                    x = -b / 2*a;
                    cout << "Delta: " << delta << endl << "Rozwiazanie jest podwojne: " <<
                    endl << "x: " << x;
                }
            else
                    cout << "Delta: " << delta << endl << "nie ma rozw w swiecie liczb rzeczywsitych";            
                
        }
    
    return 0;
}

 

komentarz 7 października 2018 przez mokrowski Mędrzec (155,460 p.)
Poczytaj o DRY.

2 odpowiedzi

+1 głos
odpowiedź 7 października 2018 przez RafalS VIP (122,820 p.)
wybrane 7 października 2018 przez Vitall
 
Najlepsza

Tu jest błąd:

x1 = (-b - sqrt(delta)) / 2 * a;

którego nie wykryłeś bo prawdopodobnie podawałeś zawsze a = 1. Wypisz sobie coś takiego:

cout<< 2.0 / 2.0 * 3.0 <<endl;

Podpowiedz - to nie będzie 0.3333 tylko 3.0. Weź mianownik w nawias.

Wypisuje -0, bo w C++ jest ujemne zero. Wstawiasz minus przed b, które jest zerem:

x = -b / 2 * a;

Jak chcesz tego uniknąc to zrób ifa na b == 0.

Jest w C++ klasa do liczb zespolonych:

    using namespace std::complex_literals;
    std::cout << std::fixed << std::setprecision(1);
 
    std::complex<double> z1 = 1i * 1i;     // imaginary unit squared
    std::cout << "i * i = " << z1 << '\n';

 

komentarz 7 października 2018 przez Vitall Początkujący (400 p.)

Dzięki wielkie, z tymi nawiasami, to wydało mi się naturalne (jak w matmie), ale faktycznie przecież C++ wykonuje działania od lewej do prawej i jeśli kumam, to najpierw sobie dzielił przez 2 a potem mnożył przez a, także nie tak jak chciałem.

Co to ifa b==0, to musiałbym go zrobić w obu miejscach: dla delta > 0 i delta == 0, bo przecież nawet jak delta > 0, to pierwiastek trójmianu zerem może być [łapię?]

Co do liczb zespolonych.. jak już mówiłem, zaczynam dopiero :P  i Twój kod nie działa mi, jeśli nie mam #include<complex>, w ogóle mam załączoną (czy to jest fachowe słowo?) całą przestrzeń nazw std, ale bez włączenia pliku complex - lipa :( Wiesz może dlaczego tak się  dzieje? Poniżej kodzik (Twój), ale działający u mnie:

 

#include<iostream>
#include<iomanip>
#include<complex>
using namespace std; // tu jest klasa complex_literals?

int main()
{
	cout << fixed << setprecision(1); 
	complex<double> z1 = 1i * 1i;     // imaginary unit squared
	cout << "i * i = " << z1 << '\n';
	cout << 2.0 / (2.0 * 3.0);
	
	return 0;
}

 

 

 

1
komentarz 7 października 2018 przez RafalS VIP (122,820 p.)

Tak. Ten kod nie działa bez załączenia odpowiedniej biblioteki. Przykład jest skopiowany z linku, który dołączyłem. Możesz tam zobaczyć na w pełni działający.

Co do ujemnego zera to znalazłem lepsze rozwiązanie. Jest funkcja, która sprawdza czy liczba jest dodatnia czy ujemna: signbit. A tutaj jest przykładowy kod. Jeśli chcesz się pozbyć ujemnego zera to zrobiłbym sobie funkcje pomocniczą do wypisywania liczb, które potencjalnie mogą być ujemnym zerem, ale generalnie na tym etapie bym się tym nie przejmował ujemnymi zerami :P

komentarz 7 października 2018 przez criss Mędrzec (172,590 p.)

Dzięki wielkie, z tymi nawiasami, to wydało mi się naturalne (jak w matmie), ale faktycznie przecież C++ wykonuje działania od lewej do prawej

Erm.. wykonuje od lewej do prawej bo mnożenie i dzielenie mają takie same priorytety. W c++ i "w matmie" też i wszędzie. Jeśli uważasz, ze mnożenie powinno być wykonane pierwsze wg zasad matematyki, to może lepiej powtórz sobie... pierwsze trzy klasy podstawówki. 

0 głosów
odpowiedź 7 października 2018 przez J0ker Pasjonat (15,400 p.)
Dodam jeszcze od siebie, że arytmetyka komputera sprawia, że aby mieć dokładniejsze wyniki, pierwiastki należy obliczyć inaczej.

Jeśli b<0, to obliczamy pierwiastek x1=-b+sqrt(delta)/2a, zaś drugi ze wzoru Vieta: x2=c/a*x1

Jeśli b>0, to obliczamy pierwiastek x1=-b-sqrt(delta)/2a, zaś drugi z tego samego wzoru Vieta.

Nie chce mi się o 21 tłumaczyć dlaczego tak jest lepiej - po prostu arytmetyka FL tak działa.
komentarz 7 października 2018 przez Vitall Początkujący (400 p.)
Ok, dzięki - doszukam sobie dlaczego ;)
komentarz 7 października 2018 przez manjaro Nałogowiec (37,390 p.)
Mały błąd z tym wzorem Viete'a. Powinno być  x2=c/(a*x1) Zresztą w tych wzorach wyżej też brakuje nawiasów ;)

Natomiast mnie bardzo zaintrygowało dlaczego tak jest lepiej. chętnie bym się dowiedział jakbyś mógł to rozwinąć i uzasadnić.
komentarz 9 października 2018 przez J0ker Pasjonat (15,400 p.)
Chodzi o to żeby unikać dodawania dwóch liczb o podobnej wartości bezwględnej i przeciwnym znaku, co może się zdarzyć przy pierwszym sposobie. Nawiasów nie chciało mi się pisać o 21 wieczorem.

Jakikolwiek skrypt z jakichś metod numerycznych poda Ci więcej. Albo Kincaid - jeszcze więcej.

Podobne pytania

0 głosów
1 odpowiedź 357 wizyt
pytanie zadane 5 lutego 2023 w C i C++ przez Martita Bywalec (2,500 p.)
0 głosów
1 odpowiedź 1,077 wizyt
0 głosów
4 odpowiedzi 302 wizyt
pytanie zadane 15 lipca 2016 w C i C++ przez Animal Użytkownik (700 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...