Wpis z mikrobloga

Mam problem z następującą funkcją w c++. Kompilator nie daje żadnego błędu, ale program się zawiesza w momencie pętli while, tak jakby liczył w nieskonczoność. Czy operator różny od może porównywać jedną liczbę int i jedną double?



void
```**```
 Fraction::decToFrac(
```**```
double
```**```
 decimal, 
```**```
double
```**```
 &nom, 
```**```
double
```**```
 &denom)

{

    nom = decimal;

    denom = 1;

    
```**```
while
```**```
(nom!=
```**```
int
```**```
(nom))

    {

        nom *=10;

        denom *=10;

``````

    }

    Fraction::Reduce(nom,denom);

}

#programowanie #cpp
  • 13
@Ronix:

nom != int(nom)


Ten warunek będzie zawsze spełniony, double nigdy nie będzie równy liczbie całkowitej (poza skrajnymi przypadkami, które możemy wykluczyć)
@blisher: Nie takimi skrajnymi, bez przesady. Wszystkie potęgi 2 w zakresie inta i całkiem sporo pozostałych liczb

double
ma dokładne odwzorowanie w

int
.

@Ronix: Obowiązkowy link: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

W skrócie: błędy zaokrąglenia nie pozwalają na spełnienie warunku, szczególnie przy mnożeniu przez 10. Lepszym rozwiązaniem byłoby mnożenie przez 2, ale wciąż bardzo prawdopodobne jest, że wyjedziesz poza zakres

int
i warunek nie będzie mógł być spełniony.
@Rincewind: Niestety nie dokładne, jak podniesiesz 2 np. do potęgi 10 i zapiszesz w double, to kompilator ci zwróci nie 1024 a coś w stylu 1023,99999988, bardzo rzadko double są równe intom
@Rincewind: jakiś pomysł jak to obejść? Mam np. 3,1415 i chce odczytać liczbę miejsc po przecinku żeby wiedzieć przez ile pomnożyć licznik i mianownik żeby dostać ułamek zwykły. 31415/10000
@blisher: Liczby zmiennoprzecinkowe są trzymane w formie

(-1)^s * m * 2^e
, gdzie s to bit znaku, m to mantysa a e to wykładnik (eksponenta). „Ułamkowość” zapisana jest w mantysie. Dla potęg 2 mantysa jest zawsze dokładnie równa 1, zmienia się tylko wykładnik. Więc wszystkie potęgi 2 mieszczące się w

int
mają dokładną reprezentację w

double
.
Pętla while, mnóż *10 tak długo, aż część ułamkowa będzie zerem


@blisher: Bez sensu, zresztą to właśnie próbuje zrobić i nie działa. W takim podejściu prędzej przekroczy zakres

int
niż zrobi ułamek.