2009-10-10 8 views
5

Kiedy próbuję pobrać N-ty root małej liczby używając C#, otrzymuję nieprawidłowy numer.Nth root małej liczby zwraca nieoczekiwany wynik w C#

Na przykład, gdy próbuję wziąć trzeci root z wersji 1.07, otrzymuję 1, co oczywiście nie jest prawdą.

Oto dokładny kod, którego używam, aby uzyskać trzeci katalog główny.

MessageBox.Show(Math.Pow(1.07,(1/3)).toString()); 

Jak mogę rozwiązać ten problem?

Przypuszczam, że jest to zagadnienie arytmetyczne zmiennoprzecinkowe, ale nie wiem, jak sobie z nim poradzić.

+2

To rzeczywiście problem, podział całkowitą. 1/3 jest obliczana jako liczba całkowita z wynikiem podziału wynoszącym 0. Tak więc naprawdę bierzesz 1.07 do potęgi 0, która wynosi 1. – tvanfosson

Odpowiedz

9

Jestem prawie pewien, że "dokładny kod", który podałeś nie kompiluje.

MessageBox.Show(Math.Pow(1.07,(1/3).toString())); 

Wezwanie do toString jest na złym poziomie zagnieżdżenia, musi być ToString i (1/3) jest liczbą całkowitą podział, który jest prawdopodobnie prawdziwy problem masz. (1/3) to 0, a cokolwiek do zerowej mocy to 1. Musisz użyć (1.0/3.0) lub (1d/3d) lub ...

+0

Drogi kapitanie sarkastycznie. Przepraszam za niesłuszne). Powinienem był skopiować i wkleić zamiast przepisywania. Poprawiłem teraz informacje. Dziękuję za doskonałą odpowiedź! –

+0

ps. pracował świetnie –

+6

Zazwyczaj nie wskazywałbym na oczywisty błąd składni, ale jakoś czułem się zobowiązany, ponieważ nie chciałeś użyć słowa "dokładny". Cieszę się, że to pomogło. –

13

C# jest traktowanie 1 i 3 jako liczby całkowite, należy wykonać następujące czynności:

Math.Pow(1.07,(1d/3d)) 

lub

Math.Pow(1.07,(1.0/3.0)) 

To jest rzeczywiście interesujący, ponieważ niejawna konwersja rozszerzenie sprawia, że ​​można zrobić błąd.

3

Po pierwsze: jeśli to jest dokładny kod, który " Re użyciu, nie jest prawdopodobne, coś nie tak z kompilatora :-)

MessageBox.Show(Math.Pow(1.07,(1/3).toString())); 

oceni (1/3) .ToString() pierwsza następnie spróbować podnieść 1.07 do potęgi tego łańcucha.

Chyba oznacza:

MessageBox.Show(Math.Pow(1.07,(1/3)).ToString()); 

odniesieniu do problemu, (1/3), jest traktowany jako podział całkowitej powrotu 0 i n wynosi 1 dla wartości n.

Musisz zmusić go do podziału zmiennoprzecinkowego z czymś takim jak 1.0/3.0.

+0

Przepraszamy za zgubione miejsce). Powinienem był skopiować i wkleić zamiast przepisywania. Poprawiłem teraz informacje. –

1

To może pomóc w przypadku gdy masz prawdziwe ntą precyzję korzeń problemu, ale moim doświadczeniem jest to, że wbudowane Math.pow (podwójne, int) jest bardziej precyzyjny:

private static decimal NthRoot(decimal baseValue, int N) 
    { 
     if (N == 1) 
      return baseValue; 
     decimal deltaX; 
     decimal x = 1M; 
     do 
     { 
      deltaX = (baseValue/Pow(x, N - 1) - x)/N; 
      x = x + deltaX; 
     } while (Math.Abs(deltaX) > 0); 
     return x; 
    } 

    private static decimal Pow(decimal a, int b) 
    { 
     if (b == 0) return 1; 
     if (a == 0) return 0; 
     if (b == 1) return a; 
     if (b % 2 == 0) 
      return Pow(a * a, b/2); 
     else if (b % 2 == 1) 
      return a * Pow(a * a, b/2); 
     return 0; 
    } 
Powiązane problemy