2011-10-29 9 views
6

Używam funkcji pow w C i zapisuję wartość zwracaną w typie całkowitym. zobacz fragment kodu poniżej:zwracana wartość pow() zostaje zaokrąglona w dół, jeśli jest przypisana do liczby całkowitej

for (i = 0; i < 5; i++){ 
    val = (int)pow(5, i); 
    printf("%d, ", val); 
} 

tutaj i i val są liczbami całkowitymi, a wyjście jest 1, 5, 24, 124, 624. Sądzę, że dzieje się tak dlatego, że float 25 jest traktowany jako 24,99999 ..., który zostaje zaokrąglony do 24 w przypadku przypisania do liczby całkowitej.

Jak mogę to zrobić, jeśli nadal potrzebuję przechowywać zwracaną wartość w int?

+0

'float' 25 nie jest" traktowany jako "' 24.9 ... ', 25 może być dokładnie przedstawiony jako float. Po prostu 'pow' nie jest w pełni dokładny iz jakiegoś powodu przy tej okazji stracił niskie. Dla wielu wartości nie może być w pełni dokładna, ponieważ poprawna matematycznie odpowiedź nie jest dokładną wartością zmiennoprzecinkową, ale w przypadku tych obliczeń może być, a zatem jest to kwestia jakości wdrożenia, niezależnie od tego, czy jest. –

+1

Zobacz również http://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int w celu omówienia sposobu wdrożenia wersji integer pow() –

+0

Nie używaj 'pow' dla całkowitej potęgi. Istnieje wiele lepszych, bezpieczniejszych sposobów. Przy okazji, na jakiej platformie korzystasz z tego zachowania? Myślałem, że dobry 'pow' będzie zawsze dokładny dla liczb całkowitych, gdzie dokładny wynik pasuje do' double'. –

Odpowiedz

9

Dodaj 0.5 przed przesłaniem do int. Jeśli twój system go obsługuje, możesz zadzwonić do funkcji C99 round(), ale wolę jej unikać ze względu na przenośność.

+3

Istnieje niewielka różnica, że ​​"runda" zaokrągla się od zera, podczas gdy dodanie 0,5 i rzucanie do rundy "int". Na przykład 'round (pow (-0.5,1))' wynosi -1, podczas gdy '(int) (pow (-0.5,1) + 0.5)' wynosi 0. Więc pytający może potrzebować zdecydować, który z nich chce, chociaż oczywiście jeśli odpowiedź jest zbliżona do liczby całkowitej, nie ma znaczenia. –

+0

"Okrągłe rundy od zera, podczas gdy dodawanie 0.5 i rzucanie do int rund w górę" - dla wartości pół-całkowitej, mam na myśli. –

+0

@JoelSpolsky: Dzięki za edycję, ale 'round()' nie jest obsługiwane na wszystkich systemach. Poprawiłem twoją edycję. –

3

Wykonaj pow siebie.

int myPow(int base, int exponent) { 
    int n = 1; 
    for (int i = 0; i < exponent; i++) { 
     n *= base; 
    } 
    return n; 
} 

To oczywiście obsługuje tylko wykładniki dodatnie i działa tylko na stronach int, a na pewno są na to bardziej wydajne sposoby. Zobacz na przykład the source for ^ in Haskell.

5

zastąpić

val = (int)pow(5, i); 

z

double d = pow(5,i); 
val = (int)((d > 0.0) ? floor(d + 0.5) : ceil(d - 0.5)); 
-3

I miał ten problem mój własny. Z łatwością rozwiązałem go w twojej instrukcji, po prostu dodaj instrukcję.

if (k%n>0) 
{ 
    k=k+1; 
} 
Powiązane problemy