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

typ danych i obliczenia matematyczne

VPS Starter Arubacloud
+1 głos
202 wizyt
pytanie zadane 17 grudnia 2015 w C i C++ przez Evelek Nałogowiec (28,960 p.)

Witam, napisałem program który liczy pewnie wyrażenie i sprawdza czy jest mniejsze od zmiennej e. Kod wygląda tak:

#include <iostream>
#include <iomanip>
#include <cmath>
#include <windows.h>
using namespace std;
int main()
{
    double p = 0;
    double wynik;
    double n;
    double q;
    double e;
    double wynik_silnia;
    double silnia;

    cout << "Podaj n: ";
    cin >> n;
    cout << "Podaj q: ";
    cin >> q;
    cout << "Podaj e: ";
    cin >> e;

    cout << setprecision(2000);

    while (wynik < e)
    {
        p++;

        silnia = 1;
        for (int i=p; i>=1; i--)
        {
            silnia*=i;
            wynik_silnia = silnia;
        }

        wynik = 1 / wynik_silnia * (pow(n-q,p-1)) * (pow(M_E,n*q));
        cout << "Dla p: " << p << " wynik wynosi: " << wynik << endl;
        Sleep(1000);
    }
    cout << "Minimalna wartosc p spelniajaca nierownosc to: " << p << endl;


    return 0;
}

 

Gdy zmienię typy zmienny na:

    long double p = 0;
    long double wynik;
    long double n;
    long double q;
    long double e;
    long double wynik_silnia;
    long double silnia;

To program nie działa. Wszystko robione dla liczb n=3, q=2, e=500. W pierwszym przypadku wychodzi 403,42...... i pętla leci sobie dalej. A w drugim przypadku pojawia się 0. Jaka tu jest różnica między tymi dwoma programami? Jak dla mnie ten drugi powinien po prostu wyświetlić większe liczby.

1 odpowiedź

0 głosów
odpowiedź 17 grudnia 2015 przez niezalogowany
wybrane 17 grudnia 2015 przez Evelek
 
Najlepsza
Wybacz, ale nie chcę się zgłębiać w kod i problem, który dokładnie chcesz rozwiązać, a jedynie zagłębię się w problem liczb zmiennoprzecinkowych.

W skrócie: w systemie dziesiątkowym wiele liczb które używamy normalnie np 0.085, to w systemie binarnym ma rozwinięcie nieskończona, a co za tym idzie precyzja tych liczb bardzo szybko się kończy, i tak jeżeli na wejściu podasz liczbę 0.85 to w komputerze na skutek aproksymacji (nie chcę wchodzić w szczegóły wzoru, polecam samemu poszukać) ta liczba zostanie zapisana jako coś w stylu (i tu jest tylko przykład): 0.85000000412345 (float), 0.85000000000000000000000000004125287 (double).

Nie liczcie zer bo mi się ich liczyć nie chciało więc nie ma prawdziwego odwzorowania float i double, to jest jedynie przykład poglądowy :P Generalnie chodzi o to że double po przecinku ma "bardziej" prawdziwą niż float, long double większą niż double.

Czyli porównanie 2 liczb, które nie są sobie równe (na np 7 miejscu po przecinku) może zwrócić true.

Kolejnym problemem jest to że część całkowita też ma wpływ na dokładność części zmiennoprzecinkowej (stąd dużo mniejsze zakresy liczb zmiennoprzecinkowych), a więc (znowu przykład, który jedynie ma coś zademonstrować) jeżeli będziemy na granicy floata jeżeli chodzi o część całkowitą, to nie będziemy  mogli używać tej samej dokładności w części zmiennoprzecinkowej, nastąpi overflow (znowu to w wynika ze wzoru jaki się stosuje do aproksymacji liczb)

A więc: częściowo mylisz się. Long double nie będzie po prostu wyświetlał większych liczb, a jedynie zwiększy swoją dokładność
komentarz 17 grudnia 2015 przez Evelek Nałogowiec (28,960 p.)
Problemem jaki chciałem rozwiązać, było sprawdzenie, dla jakiej wartości parametru p równanie: 1/p! * n-q [do potęgi] p-1 * M_E (stała e)[do potęgi] n*q, będzie większe od zmiennej e. Ułożyłem odpowiednie do tego równanie tak jak jest w linijce nr 36. Silnia wyliczona w pętli for. I teraz gdy dane mają typ zmiennej double to liczą się poprawnie, a dla typu danych long double pojawiają się jakieś nieznane mi w kompilacji błędy obliczeniowe i wyniki się nie zgadzają. Nie wiem czy ilość zer po przecinku w tym co opisałeś jest tu istotna. Ale dziękuje za teorię na ten temat.

Chodzi głównie tu o tą zamiane typu zmiennych tak jak opisałem i wytłumaczenie, czemu program się niepoprawnie liczy. :)
komentarz 3 lutego 2016 przez notabigthreat Mądrala (7,060 p.)
Zakresy liczb zmiennoprzecinkowych nie są aby większe (duże przerwy na wartościach odległych od zera)?

Podobne pytania

0 głosów
1 odpowiedź 330 wizyt
–2 głosów
2 odpowiedzi 402 wizyt
pytanie zadane 5 stycznia 2017 w C i C++ przez majmucha Nowicjusz (120 p.)
0 głosów
1 odpowiedź 150 wizyt

92,452 zapytań

141,262 odpowiedzi

319,085 komentarzy

61,854 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

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 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!

...