2012-06-16 16 views
6

Czy ktoś może mi pomóc, dlaczego x2 drukuje zero. Zgaduję, że z powodu reprezentacji zmiennoprzecinkowej X1 jest zaokrąglone, czy istnieje sposób na zachowanie precesji.Podział i punkty zmiennoprzecinkowe

long double x1, x2; 
x1= 0.087912088; // Note: 360/4095 = 0.087912088 
x2 = 360/4095; 
printf("%Lf, %Lf \n",x1, x2); 

Wynik:

x1 =0.087912 
x2= 0.000000 
+0

chris i Levon dzięki za odpowiedź. Czy istnieje sposób na zwiększenie precesji? – katta

+0

Aby faktycznie przechowywać więcej cyfr, potrzebujesz biblioteki z dowolną precyzją. Wystarczy wyświetlić więcej można zrobić, jak mówi Levon, lub z 'std :: setprecision' w C++. – chris

+0

@chris Pracuję nad niskopoziomowym kodem kontroli silnika jest C w systemie wbudowanym QNX. Będę o tym pamiętał dla kodu C++. – katta

Odpowiedz

10

Problemem jest całkowitą obcięcie .. jesteś podzielenie dwie liczby całkowite => wynik będzie inny całkowita z częścią ułamkową wyrzucać. (Na przykład w przypadku, gdy rzeczywisty wynik podziału całkowitoliczbowego wynosiłby 3,9, obcięcie spowodowałoby, że 3 (tj. Nie zaokrąglało)).

W twoim przypadku, jeśli zmienisz to:

x2 = 360/4095.0; /* one of the operands now has a decimal point */ 

dostaniesz

0.087912, 0.087912 

jako wyjście.

To znaczy, jak tylko jednej lub obu operandów operatora podziału / są pływające/podwójna wynik będzie zbyt (to znaczy będzie to „promowany” float/podwójne). Mogłem więc zmieniły x2 do

x2 = 360.0/4095.0; 

lub

x2 = 360.0/4095; 

i by zdobyć ten sam wynik jak wyżej.

Jak już wspomniałem @chris przy użyciu tylko . jest wystarczająca.

Re swoje pytanie powyżej około precyzją:

Jesteś już pracy z długimi podwaja .. Nie sądzę wewnętrznie można niczego zmieniać, chyba że używasz jakiegoś szczególnego bibliotekę, ale z pewnością można wyświetlać kolejne cyfry. Np

printf("%Lf, %.20Lf \n",x1, x2); 

przyniesie

0.087912, 0.08791208791208791895 

Wreszcie, jak @ EDA-qa mort-ORA-y przypomina nam, możesz także cast wartości do pewnych typów, ale to ma znaczenie gdy jest Ty to zrób. Prosty przykład (zauważ, że wartości skończyć jako floatpo zadanie w każdym razie od v jest float):

float v = 0; 
        /* values shown are BEFORE assignment */ 
v = (5/2);   /* value is 2 due to integer truncation before assignment */ 
v = (float) (5/2); /* 2.0 as integer division occurs 1st, then cast to float */ 
v = (float) 5/2; /* 2.5 since 5 becomes 5.0 through casting first. */ 
+0

Wystarczy kropka na końcu. – chris

+0

@chris Dzięki .. Nie zdawałem sobie sprawy, że .. nauczyłem się czegoś nowego :) Dodam to do odpowiedzi. – Levon

+0

Nauczyłem się też czegoś nowego. Dzięki faceci – katta

3

operatorów zabudowy prace nad obiektami tego samego typu. Wynik jest tego samego typu, co parametry. W tym przypadku podział jest dokonywany na dwóch liczbach całkowitych, a zatem wynik jest liczbą całkowitą.

x2 = 360/4096; 
// int/int = int 

Tak więc oczekiwałbym wyniku 0.

Jeśli operatory typu wbudowanego są różne, to promowane będą takie same typy (a wynikiem jest również ten typ). Więc chcesz:

x2 = 1.0 * 360/4095; // or 360.0/4095 

// This is 
    double * int/int 

==> (double * double)/int 
==> (double * double)/double 
Powiązane problemy