Odpowiedz na ten temat
Pokaż wyniki od 1 do 8 z 8

  1. Dołączył
    Mar 2011
    Postów
    90

    Cytuj | #1

    Witam!

    Pisząc program natrafiłem na poważny problem, dla mnie nie do przejścia.

    Opiszę co program robi:
    program najpierw wykonuje pewne operacje na liczbach a na końcu wynik pierwiastkuje i wypisuje. Potem również operuje na wyniku ale mniejsza o to.

    Problem pojawia się właśnie przy pierwiastkowaniu, proszę spójrzcie na ten przykładowy program pokazujący mój problem. Co jest nie tak?
    załączone biblioteki to i . Jak normalnie wkleić ten kod tutaj???
    Kod php:
    #include <iostream>
    #include <math.h>
    using namespace std;
    int main () {
        
    double liczba=(pow(5,10)+3); //dwie zupełnie inne liczby, ten sam wynik po pierwiastkowaniu
        
    double liczba2=(pow(5,10)+0);
        
    cout<<
        
    liczba<<"\n";
        
    cout<<
        
    sqrt(liczba)<<"\n";
        
    cout<<
        
    liczba2<<"\n";
        
    cout<<
        
    sqrt(liczba2)<<"\n";
        return 
    0;

    Wydruk z konsoli:
    9.76563e+06
    3125
    9.76562e+06
    3125
    Chodzi o problem przy dużych liczbach, np. wyświetla: 1.49012e+18. Jak zrobić, żeby wyświetlało mi normalnie? Właśnie przypuszczam, że z tego wynikają potem błędy w wyliczeniach i wszystko się sypie.
    Ostatnio edytowane przez wojtkow ; 12.10.2011 o 12:36


  2. Avatar konrado0905
    Dołączył
    Oct 2007
    Postów
    323

    Cytuj | #2

    Kod php:

    #include
    #include

    using namespace std;

    int main () 
    {[
    INDENT]double liczba=(pow(5,10)+3); //dwie zupełnie inne liczby, ten sam wynik po pierwiastkowaniu
    double liczba2=(pow(5,10)+0);

    [
    B]cout.fixed;[/B]

    cout << liczba << endl;
    cout << sqrt(liczba) << endl;
    cout << liczba2 << endl;
    cout << sqrt(liczba2) << endl;

    return 
    0;[/INDENT]} 
    Zobacz czy będzie działać. Pracuj nad czytelnością kodu.
    Ostatnio edytowane przez wojtkow ; 12.10.2011 o 12:35

  3. Avatar Krzema
    Dołączył
    Jul 2008
    Skąd
    Gdańsk, PL
    Postów
    181

    Cytuj | #3

    Koledze wyżej chodziło pewnie o
    Kod:
    cout.flags(ios::fixed);
    Co do błędów w obliczeniach, tryb wyświetlania nie ma tu nic do rzeczy. Strumień cout stara się być inteligentny i czasami za dużo zaokrągli. Poza tym zapis wykładniczy (typu "1.49012e+18") jest całkiem przyjemny, w normalnym zapisie ta liczba wyglądałaby mniej więcej tak: 1490120000000000000.
    Wszelkie niedokładności wynikają ze specyfiki formatu przechowywania liczb. Gdzieś tam jego dokładność się kończy. Zresztą można sobie policzyć dokładność Double precision floating-point format - Wikipedia, the free encyclopedia .

  4. Avatar konrado0905
    Dołączył
    Oct 2007
    Postów
    323

    Cytuj | #4

    @Krzema: Możliwe. Już się trochę pozapominało


  5. Dołączył
    Mar 2011
    Postów
    90

    Cytuj | #5

    cout.flags(ios::fixed); działa przy tych danych co były w pierwszym programie, ale jak dam już (pow(2,60)+5) lub (pow(2,60)+11) to dla niego znów to jest tym samym. Macie jakieś rady jak to zaradzić?

  6. Avatar Tojot
    Dołączył
    Feb 2008
    Postów
    743

    Cytuj | #6

    Powiedz co tak na prawdę chcesz zrobić, bez tego trudno coś doradzić. W ogólnym przypadku, to jak dla mnie, to wszystko działa tak jak należy.

    ---------- Wpis dodano o 22:40 ---------- Poprzedni wpis dodano o 22:39 ----------

    Zarządzanie błędem zaokrąglenia to dziedzina sama w sobie.
    Komputer: MacBook Pro 15" wer. MacBookPro2,2

  7. Avatar Krzema
    Dołączył
    Jul 2008
    Skąd
    Gdańsk, PL
    Postów
    181

    Cytuj | #7

    Cytat Napisał 1mysliwy1 Zobacz post
    cout.flags(ios::fixed); działa przy tych danych co były w pierwszym programie, ale jak dam już (pow(2,60)+5) lub (pow(2,60)+11) to dla niego znów to jest tym samym. Macie jakieś rady jak to zaradzić?
    Rada jest na to taka, że musisz zrozumieć jak działa double Obie te liczby, które podałeś, w ogóle nie różnią się gdy zostaną zapisane do double'a. Obie - przed spierwiastkowaniem - mają wartość 0x000000000000B043. To co tam dodajesz (5, a później 11) jest zbyt małe rzędem w stosunku do 2^60 żeby jakkolwiek wpłynęło na liczbę (w formacie double).
    Tu masz kod wypisujący daną liczbę w binarze. Pobaw się trochę, spróbuj np. dodać taką liczbę do tej 2^60, która zmieni najmłodszy bit liczby w double'u. To się da wszystko wyliczyć, ale nie ma to jak praktyka. Poza tym jeszcze raz proponuję poczytać na wiki o formatach zmiennoprzecinkowych.

    Kod php:
    #include <iostream>
    #include <cmath>
    #include <memory.h>
    using namespace std;

    int main()
    {
        
    double liczba pow(260) + 11;
        
    double pierw sqrt(liczba);

        
    char buffer[8];
        
    memcpy(buffer, &pierw8);

        for(
    int i=0i<8i++)
            
    cout << hex << (unsigned int)(buffer[i]&0xFF) << endl;

    A jeżeli potrzebujesz tak ultradokładnych obliczeń, to pewnie są odpowiednie klasy. Jak bardzo się upierasz, to jeszcze spróbuj long double.
    Ostatnio edytowane przez wojtkow ; 12.10.2011 o 12:36


  8. Dołączył
    Jan 2009
    Postów
    17

    Cytuj | #8

    Cytat Napisał 1mysliwy1 Zobacz post
    Chodzi o problem przy dużych liczbach, np. wyświetla: 1.49012e+18. Jak zrobić, żeby wyświetlało mi normalnie? Właśnie przypuszczam, że z tego wynikają potem błędy w wyliczeniach i wszystko się sypie.
    Błędy wynikają z dokładności typu zmiennej, użyj funkcji sizeof(double) która zwróci ci ilość bajtów w których przechowywana jest zmienna. U mnie double ma rozmiar 8 bajtów. Nie trudno wydedukować, że kilka bitów będzie odpowiedzialne za rząd wielkości, a na reszcie zapisuje się po prostu liczbę. Czyli komputer pamięta liczbę 976563 którą potem pomnoży przez 10 do potęgi x, gdzie x tez pamięta. Możesz użyć typu long double wtedy powinna być większa dokładność. W większości przypadków po prosu wystarczy taka dokładność, bo 400 mln i 5 zł w zasadzie dla każdego jest równa 400mln zł
    Komputer: DELL Inspiron 1501/iMac
    Telefon: iPhone 3G

Odpowiedz na ten temat