2013-06-29 10 views
10

Rozważmy następujący kod:C++ typ konwersji problem

#include <iostream> 

using namespace std; 

int aaa(int a) { 
    cout << a * 0.3 << endl; 
    return a * 0.3; 
} 

int main() 
{ 
    cout << aaa(35000); 
} 

To wypisuje:

10500 
10499 

Dlaczego wyjściowego różni?

Mam obejście do użycia "return a * 3/10;" ale nie podoba mi się to.

Edit:

Stwierdzili, że robi "pływak zwrotny (a * 0,3);" daje oczekiwaną wartość;

+0

' cout << a * 0.3' używa wyniku double. ale na drugim wyjściu przekazujesz wynik z filtru typu int. – Emadpres

Odpowiedz

8

Wynik 0,3 * 35000 jest liczba zmiennoprzecinkowa, tylko nieznacznie mniej niż 10500. Kiedy drukowany jest zaokrąglana do 10500, ale gdy zmuszony do int cyfry ułamkowe są odrzucane, co skutkuje 10499.

+0

Czy nie jest to specyficzne dla kompilatora? gcc drukuje 10500 w obu przypadkach – banarun

+1

To jest. Faktycznie, 10500 może być reprezentowane * dokładnie * jako liczba zmiennoprzecinkowa, a jeśli mnożenie odbywa się z 64 bitami, wynik powinien wynosić 10500 * zawsze *. Chodzi o to, że niektóre systemy używają 80-bitowej precyzji dla wartości pośrednich. To sprawia, że ​​0.3 jest nieco mniej niż 3/10, a gdy wynik mnożenia jest zaokrąglony, jest błędny w ostatnim bicie. – Joni

6

int * double Wydajność wyrażeń jest podwójna, to pierwsza odbitka. Następnie zamieniasz na int zajmującą się resztą (nawet jeśli jest prawie na miejscu, siedząc przy 10500-DBL_EPSILON) i przekazujesz ją ponownie. Drugi drukuje tę wartość.

Konwersje typu "float-int" należy wykonywać ostrożnie, lepiej wcale.

2

a * 0.3 ma typ double. Wezwanie wewnątrz aaa połączeń

ostream& operator<< (double val); 

natomiast jeden na zewnątrz nazywa

ostream& operator<< (int val); 

można dostać ostrzeżenie (jeśli je włączyć - Proponuję zrobić), że niejawna oddanych od double do int nie jest zalecane.

+0

Powiedz mi więcej o -I nie mogę znaleźć go w moich ustawieniach kompilatora Code :: Blocks. Przynajmniej jak to Google to. – user2534633

+0

@ user2534633 Ja jak w sobie ... Proponuję włączyć je :) –