c++ ulamek czy calkowita???

Odpowiedz Nowy wątek
Moniczka
2008-07-14 12:59
Moniczka
0

witam

mam dosc dziwne pytanie?

"jak sprawdzic czy liczba jest ulamkiem czy jest calkowita ?" czy posiada znaczy sie cos po przecinku ?:P
czekam na jakis przykladzik ,fajny przykladzik :*

pozdrawiam
Moniczka

Pozostało 580 znaków

2008-07-14 13:04

Rejestracja: 17 lat temu

Ostatnio: 3 dni temu

0

double liczba = 1..234;
if ((double)((int)liczba) == liczba) cout << "calkowita";
else cout << "z ulamkiem";


Pozostało 580 znaków

enter_sandman
2008-07-14 13:13
enter_sandman
0

Od kiedy 2 double tak się porównuje ? w ogolnym przypadku nie mozna w ten sposob rzutowac/porownywac double'i :P

//q: dokladnie tak. nie jest to prawidlowe poniewaz raz, ze chwilowe przerzutowanie na int moze zaburzyc najmniej znaczace bity double'a, a dwa ze double moze trzymac wartosci duuuzooo wieksze niz int, long, czy long long

równość dwóch zmiennych double można co najwyżej sprawdzać w pewnym małym otoczeniu.
Jak już to:

const double eps = 0.0001;
if (fabs(liczba - floor(liczba)) < eps)

Innymi slowy, podstawy metod numerycznych się kłaniają :P
Jak ktoś nie wierzy daje kod:

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

void have(double liczba) {
    if ((double)((int)liczba) == liczba)  printf("calkowita");
    else printf("z ulamkiem");
}

void have2(double liczba) {
    const double eps = 0.0000000001;
    if (fabs(liczba - floor(liczba)) < eps) printf("calkowita");
    else printf("z ulamkiem");
}

int main(int argc, char** argv) {
    double liczba = 18446744073709551616.000000;
    have(liczba);
    printf("\n");
    have2(liczba);
    printf("\n%lf %lf", liczba, liczba - floor(liczba));
    return (EXIT_SUCCESS);
}

Pozostało 580 znaków

2008-07-14 18:38

Rejestracja: 13 lat temu

Ostatnio: 7 lat temu

0

Kłania się również znajomość zakresów typów :>

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

void have(double liczba) {
    if ((double)((long long)liczba) == liczba)  printf("calkowita");
    else printf("z ulamkiem");
}

void have2(double liczba) {
    const double eps = 0.0000000001;
    if (fabs(liczba - floor(liczba)) < eps) printf("calkowita");
    else printf("z ulamkiem");
}

int main(int argc, char** argv) {
    double liczba = 18446744073709551616.000000;
    have(liczba);
    printf("\n");
    have2(liczba);
    printf("\n%.10lf %lf\n", liczba, liczba - floor(liczba));
    printf("\n%.10lf %lf\n", (double)((long long)liczba), (double)((long long)liczba) - floor((double)((long long)liczba)));
    system("pause");
    return (EXIT_SUCCESS);
}

Przy tej wartości przekręcisz nawet long long (więc nic dziwnego że daje zły wynik), ale zobacz sobie to

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

void have(double liczba) {
    if ((double)((long long)liczba) == liczba)  printf("calkowita");
    else printf("z ulamkiem");
}

void have2(double liczba) {
    const double eps = 0.0000000001;
    if (fabs(liczba - floor(liczba)) < eps) printf("calkowita");
    else printf("z ulamkiem");
}

int main(int argc, char** argv) {
    double liczba = 8446744073709551616.000000;
    have(liczba);
    printf("\n");
    have2(liczba);
    printf("\n%.10lf %lf\n", liczba, liczba - floor(liczba));
    printf("\n%.10lf %lf\n", (double)((long long)liczba), (double)((long long)liczba) - floor((double)((long long)liczba)));
    system("pause");
    return (EXIT_SUCCESS);
}

Obie linijki dają taki sam wynik :-P


Nie łam się, i tak ktoś zrobił to za ciebie
<hr style="color: #B10C0C; width: 10%; margin-left: 0" />
LUDZIE goto NIE UŻYWA SIĘ WSZĘDZIE GDZIE MOŻNA, TYLKO TAM GDZIE TRZEBA

Pozostało 580 znaków

enter_sandman
2008-07-14 18:41
enter_sandman
0

Akurat wkleiłem nie tą liczbę co chciałem, miał być 4294967295. I przy tym daje wynik poprawny.
A że 2 doubleów nie porównuje się nigdy bezpośrednio tylko w pewnym otoczeniu to jest chyba największa podstawa metod numerycznych, tego nawet w liceum uczą.

Pozostało 580 znaków

2008-07-14 18:51

Rejestracja: 13 lat temu

Ostatnio: 7 lat temu

0

Dla wartości 4294967295 też działają oba sposoby, więc nie rozumiem o co caman.

Ja nie chodziłem do liceum, tylko technikum, więc mnie tego nie nauczyli ;)
A co do porównywania, to w rzeczywistości być może tak się powinno robić, bo wyniki rzeczywiste są ciągłe. W kompie, jak byś się nie starał, to i tak sposób zapisu tych liczb sprawia, że w są ziarniste i mają skończoną dokładność. A jako takie mogą być porównywane wprost.


Nie łam się, i tak ktoś zrobił to za ciebie
<hr style="color: #B10C0C; width: 10%; margin-left: 0" />
LUDZIE goto NIE UŻYWA SIĘ WSZĘDZIE GDZIE MOŻNA, TYLKO TAM GDZIE TRZEBA

Pozostało 580 znaków

2008-07-15 15:27

Rejestracja: 14 lat temu

Ostatnio: 10 lat temu

0

Loloki, a teraz dam Ci zagadkę, do której nie użyjesz kompilatora, tylko mózgu
Powiedz, jaki wynik da następujący program i dlaczego:

#include <iostream>

using namespace std;

int main(){
    if(0.2 == 0.2) {
        cout << "T1" << endl;
    }
    if(1.2 - 1.0 == 0.2) {
        cout << "T2" << endl;
    }
    if((double) 1.2 - (double) 1.0 == (double) 0.2){
        cout << "T3" << endl;
    }
    return 0;
}

Pozostało 580 znaków

2008-07-15 17:11

Rejestracja: 16 lat temu

Ostatnio: 6 lat temu

0
enter_sandman napisał(a)

A że 2 doubleów nie porównuje się nigdy bezpośrednio tylko w pewnym otoczeniu to jest chyba największa podstawa metod numerycznych, tego nawet w liceum uczą.
W tym przypadku może być inaczej. Zapis liczby zmiennoprzecinkowej się kłania. Jeśli bity mantysy odpowiedzialne za część ułamkową są wszystkie równe zeru to liczba ta jest całkowita. Każda liczba całkowita w postaci tekstowej lub liczba typu całkowitego (np. int) po przekonwertowaniu na liczbę zmiennoprzecinkową (float/double) nadal pozostaje liczbą całkowitą (w sensie zerowej części mantysy).

I teraz, czy będziemy porównywać dokładnie, czy z pewnym otoczeniem, zależy od tego co autorka chce osiągnąć. Generalnie sprawdzanie czy liczba zmeinnoprzecinkowa jest liczbą całkowitą raczej jest złym podejściem do problemu, który można rozwiązać w zupełnie inny dokładniejszy sposób.

@Dodekam: problem zaokrągleń, który poruszyłeś wynika z konwersji pomiędzy systemem dziesiętnym a binarnym. Kod oglądamy w zapisie dziesiętnym i wydaje nam się, że 1.2 - 1.0 nie może dać innej liczby niż 0.2. Jeśli jednak zapisać by te liczby binarnie (a tak je komputer pamięta) to musielibyśmy użyć ułamka okresowego. Jak na razie procesory nie obsługują ułamków okresowych więc okres musi być ucięty. Tego problemu nie ma w przypadku stwierdzania czy liczba jest całkowita, czy nie. Jest tak dlatego, że liczba całkowita nigdy nie będzie ułamkiem okresowym, niezależnie od tego w jakim systemie ją zapiszemy. I nigdy nic nie zostanie ucięte. Zapis liczby zmiennoprzecinkowej pozwala to jasno określić. Nie istnieje podobny przykład z dodawaniem, odejmowaniem czy mnożeniem, gdzie posługując się liczbami całkowitymi (typu zmiennoprzecinkowego, np 1.0, -6.0, 15.0) wyprodukujesz w wyniku błędów zaokrągleń liczby z częścią ułamkową.

Pozostało 580 znaków

Moniczka
2008-07-15 17:22
Moniczka
0

Boze jakie wy mądre chłopaki jestescie :D:D:D ja chcialam tylko odroznic liczbe calkowiata od ulamka...czy cos jest po przecinku :) nie myslalam ze to takie trudne bedzie hihihi

pozdrawiam i buziam!!!

Pozostało 580 znaków

2008-07-15 18:05

Rejestracja: 14 lat temu

Ostatnio: 10 lat temu

0

matko, adf, ja wiem, jak działa IEEE floating point, chciałem tylko ukrócić tego cwaniaczka, co twierdzi, że double mogą być porównywane wprost...


Pozostało 580 znaków

2008-07-15 22:44

Rejestracja: 17 lat temu

Ostatnio: 3 dni temu

0

o losie.... ja prosty przykladzik dalem a tu taka burza, jakby laska znala sie ciun na metodach w dodatku numerycznych (!) to by nie pytala o "prosty przykladzik" ;p


Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0