Mnożenie float i int

0

Witam,
Mam nieco zastanawiający problem: nie rozumiem zwracanych wyników przy mnożeniu liczby int i float'a.
Oto kod źródłowy:

#include <stdio.h>

int main()
{


    float tmp=0.02;
    float tmp2=tmp*100;

    printf("%d\n",tmp2);
    printf("%d\n",(int)(tmp2));
    printf("%d\n",(int)(tmp*100));


    return 0;
}

Celowo nie ma tu możliwości wpisania danych. W każdy razie po uruchomieniu programu dostaję wyniki:
0
2
1
Skąd ta rozbieżnośc w wynikach (dlaczego tylko w jednym przypadku otrzymuję '2')?

0

Może błąd w kompilatorze?
http://ideone.com/BJWhcr daje "0 2 1"
https://www.codechef.com/ide daje "0 2 2"
http://codepad.org/eSQE2SAe daje "0 2 2"
Na moim systemie dostaję "1449499432 2 2"

Ewentualnie może to wynikać z błędów zaokrągleń. Jeżeli rzutowanie na inta nie jest zaokrąglaniem, a obcinaniem części ułamkowej to może zajść sytuacja taka, że 0.02 * 100 = 1.99999 i po obcięciu da 1.

2

Podstawowe pytanie: czemu wypisujesz zmienną typu float w formaterze integera?

0

Bo docelowo chcę wynik tego mnożenia wpisać do tablicy przechowującej int'y ;).

0

użyj funkcji roundf, a potem rzutuj na inta

0

Ja bym zaczął od jakiegoś gcc -S żeby zobaczyć co kompilator wygenerował. Zgaduje że na przykład tmp2 policzyło się na etapie kompilacji.

4

To jest undefined behavior (7.21.6/9):

printf("%d\n",tmp2);
0
rog.cc:8:19: warning: format specifies type 'int' but the argument has type 'float' [-Wformat]
    printf("%d\n",tmp2);
            ~~    ^~~~
            %f
1 warning generated.

Po poprawce wszystko jest ok: http://melpon.org/wandbox/permlink/xPrL78aIj0ImQYKw

0

Dzieki wszystkim za pomoc, ale nie rozumiem jeszcze jednego: dlaczego w tym jednym przypadku ( printf("%d\n",(int);(tmp*100))) dostaje "1"? Czy wynik nie powinien byc taki sam jak w printf("%d\n",(int)tmp2);?

0

Sorry, ze zle tam w poprzednim poscie srednik postawilem ale jestem na telefonie.

0

@suchy1270 niekoniecznie, wygeneruj asemblera / deasembluj i zobacz czy czasem nie nastąpiła prekalkulacja tego wyrażenia.

1

zaokrąglenia. Liczba 0.2 nie jest binarne dokłądnie reprezentowalna. Musi być zaokrąglona. Zależnie od zbiegu okoliczności takie liczby zaokrąglane są w górę lub w dół, więc po przemnożeniu przez 100, nie musisz dostać 20, ale np: 19.9999999995, które po konwersji do int zostanie zaokrąglone w dół i wynik wyjdzie 19.
Dlatego jeśli trzeba takie konwersje robi się tak:

auto val = static_cast<int>(tmp * (1.0 + DBL_EPSILON * 2));

albo bardziej C++

auto val = static_cast<int>(tmp * (1.0 + std::numeric_limits<double>::epsilon() * 2));
0

Shalom nie wiem jak to zrobić (zbyt zaawansowany to ja nie jestem). Fakt jest taki, że nawet odpalam programy za pomocą code: blocks, nawet nie myśląc o wierszu poleceń;c MarekR22 nie mam pojęcia jak tego użyć (ta sama przyczyna-zaawansowanie;p). Bylbym wdzięczny gdybyś wytłumaczył co mam z tym zrobić.

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