2012-06-25 10 views
8

Od http://msdn.microsoft.com/en-us/library/system.math.pow.aspxMath.pow biorąc wartość całkowitą

int value = 2; 
for (int power = 0; power <= 32; power++) 
    Console.WriteLine("{0}^{1} = {2:N0}", 
         value, power, (long) Math.Pow(value, power)); 

Math.pow trwa służyć jako argumenty, ale tutaj jesteśmy przekazując wskazówki.

Pytanie: Czy istnieje ryzyko błędu zaokrąglania wartości zmiennoprzecinkowej, jeśli występuje niejawne przekształcenie w podwójne zdarzenie?

Jeśli tak, to lepiej użyć czegoś takiego:

public static int IntPow(int x, uint pow) 
{ 
    int ret = 1; 
    while (pow != 0) 
    { 
     if ((pow & 1) == 1) 
      ret *= x; 
     x *= x; 
     pow >>= 1; 
    } 
    return ret; 
} 
+0

pokrewne pytanie: http://stackoverflow.com/questions/383587/how-do-you-do-integer-exponentiation-in-c Niektóre dobry odczyt w tej kwestii i powiązane linki – dash

+0

Zobacz też: http://stackoverflow.com/questions/936541/math-pow- – dash

+0

I [ten jeden] (http://stackoverflow.com/questions/4297454/c-sharp-math-pow-is nieprawidłowo obliczające) na błędy zaokrąglania. –

Odpowiedz

3

Tak, istnieje niejawna konwersja podwoić dzieje, i tak istnieje możliwość zmiennoprzecinkowych błędów zaokrąglania wyniku.

Co do tego, czy warto skorzystać z alternatywnej metody, którą proponujesz, jest to właściwe dla aplikacji. Czy błąd zaokrąglania zmiennoprzecinkowego jest całkowicie nie do przyjęcia? Czy użyjesz liczb, które pasują do int32 (nie potrzeba wiele, aby przepełniać moce)?

+2

Błąd zaokrąglania punktu zmiennego podczas konwersji int do podwójnego? napisz więcej o tym. –

+1

Nie jest to konwersja int do podwójnej, konwersja int do podwójnej, a następnie robienie z nią rzeczy. Jak tylko zaczniesz wykonywać dowolne operacje (dodawanie/mnożenie/cokolwiek), istnieje przynajmniej możliwość popełnienia błędów zaokrąglania. Ponieważ podniesienie do mocy prawdopodobnie zostanie podzielone na kilka add/mnoży, zwiększa prawdopodobieństwo i wielkość błędów zmiennoprzecinkowych. – Servy

+0

masz na myśli, że istnieją z dowolnym numerem IEEE 754? –

-1
public static int IntPow(int number, uint power) 
     { 
      int result = 1; 
      for (int i = 0; i < power; i++) 
      { 
       result *= number; 
      } 
      return result; 
     } 

dla czytelności!

+0

Istnieje przyczyna dodatkowego kodu - ta odpowiedź to 'O (moc)', podczas gdy kod w pytaniu, jeśli 'O (log (zasilanie))'. –

5

Nie, nie ma możliwości błędu zaokrąglenia spowodowanego konwersją na double. double może dokładnie reprezentować wszystkie liczby całkowite, które wchodzą w domenę funkcji mocy.

5

W szczególnym przypadku, gdy obliczasz 2 na moc x, możesz użyć prostej lewostronnej. To uproszczenie kodu do:

public static int TwoPowX(int power) 
{ 
    return (1<<power); 
} 
+0

A w postaci zmiennoprzecinkowej, moce dwóch można obliczyć trywialnie za pomocą 'ldexp'. Które .NET nie ma, ale jest całkiem łatwe do napisania przy użyciu 'BitConverter.Int64BitsToDouble'. –

Powiązane problemy