nth root of a number
Asked Answered
G

9

6

I wrote a program to calculate nth root of a number upto 2 decimal places. eg 4th root of 81 is 3., 3rd root of 125 is 5.Its working nicely except for the 2nd root of 4. It's giving the output 1.99 instead of 2. Here is the code.

#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;
    }
}

I have tried it for hours, but can't rectify it. can anybody debug this?? I will be very thankful.

Galaxy answered 16/8, 2010 at 15:15 Comment(6)
Please use the code button: it helps others read your code.Hartal
Sorry for the inconvenience. I am new here. Next time I will take care of this.Galaxy
ques edited. instead of 3, it is upto 2 decimal places.Galaxy
What if you change incre to 0.001? Does that help?Pero
Doesn't help. 0.0078125 makes more sense, as that has a binary representation.Her
If you need to calculate arbitrary roots, you can use double root = pow(input, 1.0 / base). For instance, the 3rd root of 10 can be calculated by pow(10, 1.0 / 3), returning 2.15443.... If you're looking for higher accuracy, check out the formulae at en.wikipedia.org/wiki/Nth_root.Pentathlon
S
10

You need to read "What Every Computer Scientist Should Know About Floating-Point Arithmetic".

Floating point numbers—which are what is normally used to represent non-integers—are inherently limited. Those limits allow good performance but at the cost of such anomalies.

Scintilla answered 16/8, 2010 at 15:28 Comment(0)
H
5

The answer, as with most floating-point problems, is that C works with a limited precision. And floats are binary. They can't exactly represent the decimal number 1.99 - it will likely be a close value like 1.990000000023.....

Standard link for these problems: What Every Computer Scientist Should Know About Floating-Point

There's luckily an easy solution (but not perfect!). Find the root of (num*10000.0), using increments of one. This will be of course 100 times the root that you really want. Hence, the last two digits are the "decimal places" you wanted. You'll find that the root of 40000.0 is precisely 200.0 This works because 1.0 can be perfectly represented.

The price you pay for for precision at that end is that you lose it on the other end - multiplying by 10000 means you'll get a loss of precision with higher numbers. Easy solutions rarely come without drawbacks, sorry.

Her answered 16/8, 2010 at 15:18 Comment(2)
but why it's not going upto 2. My condition for break is a<k. if we input a = 4 then the value of k is square of 1.99. So it can't be greater then 4. Why the loop is breaking?Galaxy
Same thing. It can't represent the number 0.01 either. It will something like be 0.009999999999984.... Hence, 0.01 + 0.01 will be 0.019999999999968... . And 0.01 + 0.01 + 0.01 + 0.01 (times 199) will cause 198 rounding errors.Her
M
5

That's because computers can't handle real numbers properly.

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

Marcelo answered 16/8, 2010 at 15:19 Comment(2)
More specifically, computers can't handle infinite precision. All objects, including all numbers, which includes all floating-point numbers, are represented by a finite set of bytes.Ursine
@Loadmaster: even more specifically: computers handle indefinite precision as humans do: symbolically.Scintilla
G
2

Well, if you want 0.01 accuracy, you need step 0.005 or less, and then perform rounding. The best way is to just use pow(num1, 1/n) :-)

Guthrun answered 16/8, 2010 at 15:20 Comment(0)
B
2

take 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;
    }
}
Bannock answered 30/6, 2011 at 4:51 Comment(0)
R
1

what MSalters said. try making incre smaller to see how the value gradually approaches 2.0. you might want to have a higher "internal" precision (ie incre) that what you return, and round the internal result to, say, 2 digits. This way you might cover those rounding problems (but it's just an untested suspicion)

Respect answered 16/8, 2010 at 15:21 Comment(1)
It doesn't work, in fact more rounding errors will accumulate. He currently has 199 rounding errors, all at 1up. Decreasing the increment to 0.001 means you'll have 1999 rounding errors, still at 1 up. Now 1up of 0.001 is a bit smaller, but it's hardly progress. Also, you're adding 1998 times instead of 198 times, which again means you have more but smaller rounding errors.Her
A
0

Doubles cannot necessarily represent floating point numbers accurately. Try using a decimal datatype instead (if c has such a think, sorry can't remember). C# has decimal, Java has BigDecimal classes to represent floating point numbers accurately.

Autophyte answered 16/8, 2010 at 15:21 Comment(0)
I
0

A smaller "incre" value should work, I used 0.001 and root1 returned 2.00 for the square root of 4.

Also, if you want the answer to be displayed to 2 decimal places, use %.2f when you print the root.

Ipa answered 16/8, 2010 at 15:35 Comment(0)
H
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;
}

Why to write such huge code.This works perfectly until i change double to int.

Higginbotham answered 14/8, 2014 at 16:57 Comment(1)
Are you trying to help the OP or insult him?Electropositive

© 2022 - 2024 — McMap. All rights reserved.