[C] Prosty kalkulator liczb rzeczywistych

M Franek52525
Użytkownik
Użytkownik
Posty: 11
Rejestracja: 3 lut 2011, o 12:51
Płeć: Mężczyzna

[C] Prosty kalkulator liczb rzeczywistych

Post autor: M Franek52525 » 27 lip 2011, o 10:27

Proszę o pomoc w zrozumieniu dlaczego ten program wyświetla ciągle zły wynik:

Kod: Zaznacz cały

#include<stdio.h>
int main()
{
    signed long x,y,z;
    printf("Podaj x:
");
    scanf("%f",&x);
    printf("Podaj y:
");
    scanf("%f",&y);
    z=x+y;
    printf("x+y=%g
",z);
    return 0;
} 
Ostatnio zmieniony 27 lip 2011, o 19:45 przez M Franek52525, łącznie zmieniany 3 razy.

Awatar użytkownika
thenighthawk4
Użytkownik
Użytkownik
Posty: 76
Rejestracja: 31 sty 2011, o 20:18
Płeć: Mężczyzna
Podziękował: 1 raz
Pomógł: 7 razy

[C] Prosty kalkulator liczb rzeczywistych

Post autor: thenighthawk4 » 27 lip 2011, o 11:38

Spójrz:

Kod: Zaznacz cały

signed long x,y,z;
i porównaj z tym:

Kod: Zaznacz cały

scanf("%f",&x);
oraz z tym:

Kod: Zaznacz cały

printf("x+y=%g
",z);
Zastanów się, co widzisz dziwnego?
Co robi parametr %f i %g?

M Franek52525
Użytkownik
Użytkownik
Posty: 11
Rejestracja: 3 lut 2011, o 12:51
Płeć: Mężczyzna

[C] Prosty kalkulator liczb rzeczywistych

Post autor: M Franek52525 » 27 lip 2011, o 11:59

%f i%g w funkcji scanf służy do odczytu liczb rzeczywistych.
W printf nie ma takiego formatu. Czy o to chodzi?

Awatar użytkownika
thenighthawk4
Użytkownik
Użytkownik
Posty: 76
Rejestracja: 31 sty 2011, o 20:18
Płeć: Mężczyzna
Podziękował: 1 raz
Pomógł: 7 razy

[C] Prosty kalkulator liczb rzeczywistych

Post autor: thenighthawk4 » 27 lip 2011, o 12:03

Jakiego typu zmienne zadeklarowałeś? Czy przeznaczone dla liczb rzeczywistych?

M Franek52525
Użytkownik
Użytkownik
Posty: 11
Rejestracja: 3 lut 2011, o 12:51
Płeć: Mężczyzna

[C] Prosty kalkulator liczb rzeczywistych

Post autor: M Franek52525 » 27 lip 2011, o 12:08

Aha faktycznie nie doczytałem, że to do liczb całkowitych
Zmieniłem na float i działa, tylko nie mogę wymyślić co z long double?

Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C] Prosty kalkulator liczb rzeczywistych

Post autor: Afish » 27 lip 2011, o 13:07

http://www.cplusplus.com/reference/clib ... dio/scanf/
Specifies a size different from int (in the case of d, i and n), unsigned int (in the case of o, u and x) or float (in the case of e, f and g) for the data pointed by the corresponding additional argument:
h : short int (for d, i and n), or unsigned short int (for o, u and x)
l : long int (for d, i and n), or unsigned long int (for o, u and x), or double (for e, f and g)
L : long double (for e, f and g)

M Franek52525
Użytkownik
Użytkownik
Posty: 11
Rejestracja: 3 lut 2011, o 12:51
Płeć: Mężczyzna

[C] Prosty kalkulator liczb rzeczywistych

Post autor: M Franek52525 » 29 lip 2011, o 11:29

Nie wiem jak mam mam wpisać te specyfikatory rozmiaru żeby to działało.

Awatar użytkownika
thenighthawk4
Użytkownik
Użytkownik
Posty: 76
Rejestracja: 31 sty 2011, o 20:18
Płeć: Mężczyzna
Podziękował: 1 raz
Pomógł: 7 razy

[C] Prosty kalkulator liczb rzeczywistych

Post autor: thenighthawk4 » 29 lip 2011, o 15:08

Mógłbyś napisać jak próbowałeś to zrobić?
Co nie działa? Pokaż kod po modyfikacjach, pokaż przykładowe wejście i wyjście.
Jakiego kompilatora używasz?

Napisałem tak:

Kod: Zaznacz cały

#include <stdio.h>

int main()
{
	long double x,y,z;
	printf("Podaj x:
");
	scanf("%Lf",&x);
	printf("Podaj y:
");
	scanf("%Lf",&y);
	z=x+y;
	printf("x+y=%Lf
", z);
	
	return 0;
}
Na Linuksie działa bezproblemowo, jednak na Windowsie (MinGW) printf wypisuje za każdym razem -2.
Z tego, co wyczytałem, MinGW sprawia problemy przy połączeniu long double z printf i scanf

http://oldwiki.mingw.org/index.php/long%20double

W ogóle po co Ci tak wielkie liczby?

M Franek52525
Użytkownik
Użytkownik
Posty: 11
Rejestracja: 3 lut 2011, o 12:51
Płeć: Mężczyzna

[C] Prosty kalkulator liczb rzeczywistych

Post autor: M Franek52525 » 29 lip 2011, o 21:41

Ja używam programu code blocks.
Próbowałem tak:

Kod: Zaznacz cały

#include<stdio.h>
int main()
{
    long double x,y,z;
    printf("Podaj x:
");
    scanf("%Lg",&x);
    printf("Podaj y:
");
    scanf("%Lg",&y);
    z=x+y;
    printf("x+y=%Lg
",z);
    return 0;
}
Efektem tego jest wynik=-2.
Po prostu chce zrobić ten kalkulator na tak dużych liczbach, żeby się w końcu czegoś nauczyć.
Pomimo, że będzie można wykonać tylko jedną operację naraz.

Awatar użytkownika
thenighthawk4
Użytkownik
Użytkownik
Posty: 76
Rejestracja: 31 sty 2011, o 20:18
Płeć: Mężczyzna
Podziękował: 1 raz
Pomógł: 7 razy

[C] Prosty kalkulator liczb rzeczywistych

Post autor: thenighthawk4 » 1 sie 2011, o 23:58

Code::Blocks to środowisko programistyczne.
Upewnij się jakiego kompilatora używasz.
Jeśli twój system to Windows, prawdopodobnie korzystasz z GCC dostarczanego przez MinGW.

Na temat problemów z MinGW podałem już linka. Nie wiem, czy można je obejść przy zachowaniu pełnej funkcjonalności typu long double. Ostatecznie możesz użyć innego kompilatora, który wspierałby w pełni ten typ lub wyemigrować na Pingwina

Ilu miejsc po przecinku potrzebujesz? Może wystarczy odpowiednio sformatować wyjście
(patrz printf na http://cplusplus.com/reference/).

Sprawdziłem działanie long double w środowisku Code::Blocks na kompilatorze LCC.
Program oblicza wartość \(\displaystyle{ \sqrt{2}}\) za pomocą funkcji z math.h, oraz implementacji metody Newtona-Raphsona (nie napisałem jej za dobrze) dla typów double i long double.

Kod: Zaznacz cały

#include <stdio.h>
#include <math.h>

long double PierwiastekL(long double &val, unsigned int n);
double Pierwiastek(double &val, unsigned int n);

int main()
{
    long double lox, loz;
    double x, z;

    printf("Podaj lox:
");
    scanf("%Lf",&lox);

    printf("Podaj x:
");
    scanf("%lf",&x);

    loz = sqrt(lox);
    printf("loz=%.25Lf
", loz);
    loz = PierwiastekL(lox, 2);
    printf("loz=%.25Lf
", loz);

    z = sqrt(x);
    printf("  z=%.25lf
", z);
    z = Pierwiastek(x , 2);
    printf("  z=%.25lf
", z);

    return 0;
}

long double PierwiastekL(long double &val, unsigned int n)
{
    const long double d = 0.00000000000000001;
    long double a = 1;

    while( fabs(val - pow(a, n)) > d )
        a = ( val/pow(a, n-1) + (n-1)*a ) / n;

    return a;
}

double Pierwiastek(double &val, unsigned int n)
{
    const double d = 0.000000000000001;
    double a = 1;

    while( fabs(val - pow(a, n)) > d )
        a = ( val/pow(a, n-1) + (n-1)*a ) / n;

    return a;
}
Zmienne lokalne d mają maksymalną ilość miejsc po przecinku, która nie sprawiała u mnie problemów.

Rezultat sam oceń:

Kod: Zaznacz cały

loz=1.4142135623730950490000000
loz=1.4142135623730950490000000
  z=1.4142135623730950000000000
  z=1.4142135623730950000000000

M Franek52525
Użytkownik
Użytkownik
Posty: 11
Rejestracja: 3 lut 2011, o 12:51
Płeć: Mężczyzna

[C] Prosty kalkulator liczb rzeczywistych

Post autor: M Franek52525 » 7 sie 2011, o 15:44

U mnie nie chce działać

void_t
Użytkownik
Użytkownik
Posty: 103
Rejestracja: 14 maja 2011, o 18:25
Płeć: Mężczyzna
Pomógł: 26 razy

[C] Prosty kalkulator liczb rzeczywistych

Post autor: void_t » 7 sie 2011, o 21:01

Nie chce działać z jakiego powodu? Nie kompiluje sie?

M Franek52525
Użytkownik
Użytkownik
Posty: 11
Rejestracja: 3 lut 2011, o 12:51
Płeć: Mężczyzna

[C] Prosty kalkulator liczb rzeczywistych

Post autor: M Franek52525 » 8 sie 2011, o 14:37

Tak, nie chce się skompilować

void_t
Użytkownik
Użytkownik
Posty: 103
Rejestracja: 14 maja 2011, o 18:25
Płeć: Mężczyzna
Pomógł: 26 razy

[C] Prosty kalkulator liczb rzeczywistych

Post autor: void_t » 8 sie 2011, o 14:42

Nic dziwnego. thenighthawk4 najprawdopodobniej omyłkowo zastosował 2, wykluczające się w tym aspekcie składnie - C i C++.

Kod: Zaznacz cały

long double PierwiastekL(long double &val, unsigned int n);
double Pierwiastek(double &val, unsigned int n);
Powinno być (dla C):

Kod: Zaznacz cały

long double PierwiastekL(long double *val, unsigned int n);
double Pierwiastek(double *val, unsigned int n);
A co za tym idzie:

Kod: Zaznacz cały

loz = PierwiastekL(lox, 2);
Na

Kod: Zaznacz cały

loz = PierwiastekL(&lox, 2);

Kod: Zaznacz cały

loz = PierwiastekL(lox, 2);
Na

Kod: Zaznacz cały

loz = PierwiastekL(&lox, 2);
Oraz w kodzie typu

Kod: Zaznacz cały

 while( fabs(val - pow(a, n)) > d )
        a = ( val/pow(a, n-1) + (n-1)*a ) / n;
Zamienić należy 'val' na *val, jako że odwołujemy się do wartości tego na co wskazuje pointer, a nie do adresu tego czegoś.

Ponadto w funkcji PierwiastekL funkcje fabs i pow powinny zostać zamienione na fabsl oraz powl, bowiem operujemy na typie long double a nie double

Awatar użytkownika
thenighthawk4
Użytkownik
Użytkownik
Posty: 76
Rejestracja: 31 sty 2011, o 20:18
Płeć: Mężczyzna
Podziękował: 1 raz
Pomógł: 7 razy

[C] Prosty kalkulator liczb rzeczywistych

Post autor: thenighthawk4 » 8 sie 2011, o 16:53

void_t, rzeczywiście pomieszałem C z C++, jednak zastanawiam się, dlaczego u mnie się to skompilowało zarówno w GCC, jak i w LCC.

Co do pow i fabs, nie ma to jak kopiowanie kodu
Poprawiłem według Twoich zaleceń, jednak wyjście nie uległo zmianie, precyzja pozostaje ta sama.

Nie wiem, czy może źle zrobiłem coś przy ograniczeniu zmienną d, czy typ argumentu (double/long double) nie ma tutaj znaczenia?
Sądząc po tym: http://www.cplusplus.com/reference/clibrary/cmath/sqrt/ funkcja sqrt jest rzutowana na odpowiedni typ, a wydaje mi się, że 2-3 miejsca po przecinku, to stosunkowo mało jak na 2 dodatkowe bajty. Próbowałem też z sqrtl.
O co może tu chodzić?

ODPOWIEDZ