2010-08-16 13 views
6

Napisałem program do obliczania n-tego katalogu głównego liczby do 2 miejsc dziesiętnych. np. 4. root z 81 jest 3., 3. root z 125 jest 5. Działa ładnie, z wyjątkiem drugiego korzenia 4. Daje wynik 1,99 zamiast 2. Oto kod.nth root z numeru

#include<stdio.h> 
int main(int argc, char **argv) 
{ 
    double root1(int,int); 
    int n; 
    int num1; 
    double root; 
    printf("\n\n-----------This is the programme to find the nth root of a number-----------\n\n"); 
    printf("Enter a nuber greater then 1 : "); 
    scanf("%d",&num1); 
    if(num1>1) 
    { 
     printf("Enter the value for 'n'(the root to be calculated) : "); 
     scanf("%d",&n); 
     root = root1(num1,n); 
     printf("%d th Root of %d is %f\n\n", n,num1,root); 
    } 
    else 
     printf("wrong entry"); 
    return 0; 
} 

double root1(int a, int b) 
{ 
    int j; 
    double i,k; 
    double incre = 0.01; 
    for(i=1; i<=a; i = i+incre) 
    { 
     for(j=0;j<b;j++) 
     { 
      k=k*i; 
     } 
     if(a<k) 
     { 
      return(i-incre); 
      break; 
     } 
     else 
      k=1; 
    } 
} 

Próbowałem go przez wiele godzin, ale nie można go naprawić. Czy ktoś może to debugować? Będę bardzo wdzięczny.

+0

Proszę użyć przycisku kodu: pomaga innym odczytać kod. –

+0

Przepraszamy za niedogodności. Jestem tu nowy. Następnym razem zajmę się tym. – narayanpatra

+0

pytania edytowane. zamiast 3 jest to 2 miejsca dziesiętne. – narayanpatra

Odpowiedz

5

Odpowiedź, podobnie jak w przypadku większości zagadnień zmiennoprzecinkowych, polega na tym, że C działa z ograniczoną precyzją. A zmiennoprzecinkowe są binarne. Nie mogą dokładnie reprezentować liczby dziesiętnej 1,99 - prawdopodobnie będzie to bliska wartość, taka jak 1.990000000023.....

Link Standard dla tych problemów: What Every Computer Scientist Should Know About Floating-Point

Jest na szczęście proste rozwiązanie (ale nie jest doskonały!). Znajdź katalog główny (liczba * 10000.0), używając przyrostów o jeden. Będzie to oczywiście 100 razy więcej niż root, którego naprawdę chcesz. Dlatego ostatnie dwie cyfry to "miejsca dziesiętne", które chciałeś. Przekonasz się, że root 40000.0 wynosi dokładnie 200.0 Działa to, ponieważ 1.0 może być doskonale reprezentowany.

Cena, którą płacisz za precyzję na tym końcu, polega na tym, że tracisz ją na drugim końcu - pomnożenie przez 10000 oznacza utratę precyzji przy wyższych liczbach. Łatwe rozwiązania rzadko pojawiają się bez wad, przepraszam.

+0

, ale dlaczego nie idzie do góry 2. Mój warunek do przerwy to narayanpatra

+2

To samo. Nie może również reprezentować liczby "0.01". Będzie to coś w stylu '0.009999999999984 ...'. Dlatego 0,01 + 0,01 będzie "0.019999999999968 ...". A 0,01 + 0,01 + 0,01 + 0,01 (199) spowoduje 198 błędów zaokrąglania. – MSalters

+0

Dzięki stary. Wszystkie te informacje są dla mnie bardzo przydatne. – narayanpatra

6

Dzieje się tak, ponieważ komputery nie mogą poprawnie obsługiwać liczb rzeczywistych.

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

+3

Dokładniej, komputery nie mogą obsłużyć * nieskończonej precyzji *. Wszystkie obiekty, w tym wszystkie liczby, które zawierają wszystkie liczby zmiennoprzecinkowe, są reprezentowane przez skończony zestaw bajtów. –

+3

@ Ladadmaster: jeszcze dokładniej: komputery radzą sobie z nieokreśloną precyzją tak jak ludzie: symbolicznie. – Richard

2

Cóż, jeśli chcesz 0,01 dokładność, trzeba krok 0,005 lub mniej, a następnie wykonać zaokrąglenia. Najlepszym sposobem jest użycie tylko pow (liczba 1, 1/n) :-)

0

Podwaja niekoniecznie przedstawia dokładnie liczby zmiennoprzecinkowe. Zamiast tego spróbuj użyć dziesiętnego typu danych (jeśli c ma takie zdanie, niestety nie pamięta). C# ma dziesiętny, Java ma klasy BigDecimal do reprezentowania liczb zmiennoprzecinkowych dokładnie.

1

co MSalters powiedział. spróbuj zmniejszyć rozmiar o incre, aby zobaczyć, jak stopniowo zbliża się wartość do wersji 2.0. możesz chcieć mieć wyższą "wewnętrzną" precyzję (tj. wzrost) tego, co powrócisz, i zaokrąglić wewnętrzny wynik do, powiedzmy, 2 cyfr. W ten sposób możesz pokryć problemy związane z zaokrąglaniem (ale to tylko niesprawdzone podejrzenie).

+0

To nie działa, w rzeczywistości więcej błędów zaokrąglania będzie się kumulować. Obecnie ma 199 błędów zaokrągleń, wszystkie w 1up. Zmniejszenie tego przyrostu do 0,001 oznacza, że ​​będziesz miał zaokrąglenia z 1999 r., Wciąż o 1 w górę. Teraz 1up z 0,001 jest nieco mniejszy, ale prawie się nie rozwija. Dodajesz także 1998 razy zamiast 198 razy, co oznacza, że ​​masz więcej, ale mniejszych błędów zaokrąglania. – MSalters

0

Mniejsza „incre” wartość powinna działać, użyłem 0,001 KatalogGłówny1 powrócił 2,00 dla pierwiastka kwadratowego 4.

Ponadto, jeśli chcesz, odpowiedź ma być wyświetlany do 2 miejsc po przecinku, użyj% .2f kiedy drukujesz root.

2

weź k = 1;

#include<stdio.h> 
int main(int argc, char **argv) 
{ 
    double root1(int,int); 
    int n; 
    int num1; 
    double root; 
    printf("\n\n-----------This is the programme to find the nth root of a number-----------\n\n"); 
    printf("Enter a nuber greater then 1 : "); 
    scanf("%d",&num1); 
    if(num1>1) 
    { 
     printf("Enter the value for 'n'(the root to be calculated) : "); 
     scanf("%d",&n); 
     root = root1(num1,n); 
     printf("%d th Root of %d is %f\n\n", n,num1,root); 
    } 
    else 
     printf("wrong entry"); 
    return 0; 
} 

double root1(int a, int b) 
{ 
    int j; 
    double i,k=1; 
    double incre = 0.01; 
    for(i=1; i<=a; i = i+incre) 
    { 
     for(j=0;j<b;j++) 
     { 
      k=k*i; 
     } 
     if(a<k) 
     { 
      return(i-incre); 
      break; 
     } 
     else 
      k=1; 
    } 
} 
0
#include <iostream> 
#include<math.h> 
using namespace std; 
int main() 
{ 
double n,m; 
cin>>n; 
cin>>m; 
m= pow(m, (1/n)); 
cout<<m; 
return 0; 
} 

Dlaczego pisać takie ogromne code.This działa idealnie, dopóki nie zmieni double do int.

+0

Czy próbujesz pomóc OP lub go znieważyć? –