Finding approximate square root of a number - c

This is the code which I have written to find approx square root a non perfect number(in the order 0.0001 and also exact square root of a perfect square. It is working with non perfect square numbers but not perfect. When I put 25 it gives 5.000068
#include<stdio.h>
int main()
{
float a,i,count;
scanf("%f",&a);
for(count=1;(1);count=count+0.0001)
{
i=count*count;
if (i<=a)
break;
}
printf("%f",count);
return 0;
}

Your method is wrong for computing square roots.
You deserve a bad grade for not reading a bit about square roots. Understanding the problem is the first step for any software development.
First, you should read The Floating Point Guide and the classical What Every Programmer Should Know About Floating-Point Arithmetic. It explains why your program cannot work (i.e. gives inaccurate results).
Then, your program is very inefficient (for large input numbers like several billions, it takes an enormous amount of computing time; for very small numbers like 0.01 it probably never terminates). Learn about Newton-Raphson's method, perhaps by reading some basic math book.
Notice that many fixpoint computations translate to iterative algorithms.

There are two things that are faulty with your code:
Floating point is not exact. If you want more accuracy, use double, not float.
Your increment value is too large. If you incremented by a smaller amount you would (or should) get the desired value: See here: http://ideone.com/7XM2IK
The next issue doesn't affect your code now, but be warned anyway:
Do not use floating point arithmetic as a loop counter. To fix this issue, normalize your loop to do integer counts, and do the floating point inside the loop:
int count;
float dCount = 1.0;
float i, a;
//...
for (count=0; count < 100000; ++count)
{
//...
}
See this link: https://www.securecoding.cert.org/confluence/display/java/NUM09-J.+Do+not+use+floating-point+variables+as+loop+counters

If you dont want to struggle with books and math:
#include <stdio.h>
#include <math.h>
int main()
{
float n = 25;// ofc use scanf xD
n=sqrt(n);
printf("%.5f", n);
return 0;
}

Related

Is there a way to run the following code for CS50 Cash problem set 1

I'm very new to CS and programming and am trying to write a code for the cs cash problem set 1.I don't think this is the intended solution and I know this isn't a clean and condensed code, but at this point I'm just trying to make it run.I was wondering if the code I wrote was complete gibberish or if it could actually work because it honestly made sense to me theoretically.
#include<stdio.h>
#include<cs50.h>
#include<math.h>
int main(void)
{
float change;
do
{
change= get_float("Enter change here\n");
}
while(change<0);
int quarter=floor(change/0.25);
int dime=floor((change-(quarter*0.25))/0.10);
int nickel=floor((change-(quarter*0.25)-(dime*0.10))/0.05);
int penny=round((change-(quarter*0.25)-(dime*0.10)-(nickel*0.05))/0.01);
int sum =quarter+nickel+dime+penny;
printf("%i",sum);
}
This is a common issue that many beginners struggle with, which is the imprecision on floating point numbers. When doing operations with floats and doubles, it's possible for the resulting value to be off by a small decimal. You can learn more about it on this SO post: Why are floating point numbers inaccurate?.
Anyways, your program involves float division and integer truncation, which usually don't work well together. In the example of $4.20 as input, after quarters has been set to 16, when calculating dimes, (4.2 - 0.25 x 16) / 0.10 is actually saved as 1.999998, instead of 2. This is then truncated (since dime is an int) and saved as 1, which explains the inaccurate outputs that your program is giving you. A solution would be to multiply everything by 100, using integer division to avoid imprecision. So the above example would become (420 - 25 x 16) / 10, which will correctly be saved as 2 in your dime int.

How to find empty space in a rectangle which has 2 circles in it?

I'm solving a problem in Toph . In this problem I've to find out the empty space of a rectangle which has 2 equal circles in it.
here is the problem
#include <stdio.h>
float pi=3.1416;
int main()
{
int i,t;
float r,rest;
scanf("%d",&t);
for(i=1;i<=t;i++)
{
scanf("%f",&r);
rest=(4*r*2*r)-(2*pi*r*r);
printf("Case %d: %.2f\n",i,rest);
}
return 0;
Here is my solve. It returns a correct value for first test case but it fails to solve the second one.
What's the problem???
float pi=3.1416; is the cause of the problem. Under the math header file (#include <math.h>) there is a constant M_PI use it instead.
Edit:
Sorry, didn't read thoroughly, apparently the problem is in the floating point precision. If you change all float values into double it should work.
#include <stdio.h>
double pi=3.1416;
int main()
{
int i,t;
double r,rest;
scanf("%d",&t);
for(i=1;i<=t;i++)
{
scanf("%lf",&r);
rest=(4*r*2*r)-(2*pi*r*r);
printf("Case %d: %.2lf\n",i,rest);
}
return 0;
}
Unlike 2 and 8, the reason double is more accurate is because float cannot represent 3.1416 as well as the input values:
3.1416 -> 3.1415998935699462890625
40.082 -> 40.082000732421875
85.8 -> 85.8000030517578125
There's simply not enough precision, (note that IEEE-754 float, which is overwhelmingly used for float, stores it in base-2.) Most probably, the later numbers were probably specifically generated in order to fail the test cases. If one wants to know more, Don’t Store That in a Float, and What Every Computer Scientist Should Know About Floating-Point Arithmetic.
The numerical constant is 1.7168, which is exact assuming their version of pi, (times r*r.) The best one could with single-point precision is 1.7167999744415283203125, which is off by 2.55584716796875E-8. With a double, it's 1.71680000000000010373923942097, off by 1.0373923942097E-16, plus the values input.

Cube root using Newton Raphson

This is a code that I wrote to find the cube root of a number using Newton Raphson. However, it always shows the answer as -1#IND0. Can you help me find what is wrong with this code?
#include <stdio.h>
int main()
{
float x_0,x,x_m,n;
int m,i=0;
printf("Enter integer you wish to find the cube root of: ");
scanf("%f",&n);
printf("\nEnter your first guess and number of steps: ");
scanf("%f %d",&x_0,&m);
x_m=(1/3)*((2*x_0)+(n/(x_0*x_0)));
// printf("\nx_m=%f\nx_0=%f\nm=%d",x_m,x_0,m);
while( i<m)
{
x=x_m;
x_m=(1/3)*((2*x)+(n/(x*x)));
i++;
}
printf("\nThe cube root of %.0f is approximately %.5f",n,x_m);
return 0;
}
Before the loop starts, m_x will be zero since (1/3) is zero (integer division).
On the first iteration, (n/(x*x)) is then a poll as x will be zero. That accounts for the output being -1#IND0.
The fix, as always, is to remove all those extra parentheses that folk always seem to put in:
x_m=(2*x + n/(x*x))/3;
&c. (although your duplication of the Newton Raphson formula is unsatisfactory - as you have to put the fix in two places.). Because x is a floating point type, all the arithmetic will be performed in floating point, due to the sensible rules of type promotion.
After you've fixed this, bin it and use cbrt, from the C standard library header math.h.
Before the while you have
x_m=(1/3)*((2*x_0)+(n/(x_0*x_0)));
Since 1/3 will yield 0, x_m will be 0. And then you have
x_m=(1/3)*((2*x)+(n/(x*x)));
where you use x*x as a quantity to divide n with. Since x is 0, the result will have an undefined behavior. Try to make sure the amount you divide with is not 0, but a valid value, start with (1.0/3).

asin() function in C returns NaN when more iterations used

I have a homework in C. We have to write our own asin() function with Taylor method, and we can't use math.h
It works fine, but once I put higher count of iterations(int i), it returns NaN(Not a Number), and when I use low count of i, the number is not exact. Can anyone help me with this?
double my_asin(double x)
{
int i = 0;
double vypocet = x;
double y = vypocet;
for(i=1;i<=10000;i++)
{
vypocet*=((x*x)*(2*i-1)*(2*i-1))/((2*i)*(2*i+1));
y+=vypocet;
}
printf("my_asin = %.10e\n", y);
return y;
}
EDIT: Thank you all! finished it :)
Two things are required for your answer :
Regarding maths : The series expansion you are coding is a sin inverse (arcsin) and expecting an output in radian.
sin^(-1)x=x+1/6x^3+3/(40)x^5+5/(112)x^7+(35)/(1152)x^9+... . As you can see this is an expansion which is monotonically increasing and expecting value (input) between [-1,1] only. When you plug in large values e.g. 10 you are bound to get results you don't expect.So , plug in correct values. I guess, put correct values [-1,1] when calling the function my_asin() and your code would work fine FOR THE number of ITERATIONS YOU HAVE NOW.
e.g 1.5146343691e+000 looks fine for 90 degrees or pi/2 or my_asin(1).
2 .Regarding Floating Point (double i.e. single prrecision floating point ):They cant represent all the numbers on the real line, their range is a subset of R.And when there is a number that can't be represented correctly by their 32 bits encoding (IEEE 754) you will get error in result.
Number as simple as 0.1 cant be represented exactly using floating point.
Check these pages for FP Errors and FP Exceptions :
http://www.gnu.org/software/libc/manual/html_node/Infinity-and-NaN.html
http://www.gnu.org/software/libc/manual/html_node/FP-Exceptions.html#FP-Exceptions

Taylor Series in C

I'm trying to make a program to calculate the cos(x) function using taylor series so far I've got this:
int factorial(int a){
if(a < 0)
return 0;
else if(a==0 || a==1)
return 1;
else
return a*(factorial(a-1));
}
double Tserie(float angle, int repetitions){
double series = 0.0;
float i;
for(i = 0.0; i < repeticiones; i++){
series += (pow(-1, i) * pow(angle, 2*i))/factorial(2*i);
printf("%f\n", (pow(-1, i) * pow(angle, 2*i))/factorial(2*i));
}
return series;
}
For my example I'm using angle = 90, and repetitions = 20, to calculate cos(90) but it's useless I just keep getting values close to the infinite, any help will be greatly appreciated.
For one thing, the angle is in radians, so for a 90 degree angle, you'd need to pass M_PI/2.
Also, you should avoid recursive functions for something as trivial as factorials, it would take 1/4 the effort to write it iteratively and it would perform a lot better. You don't actually even need it, you can keep the factorial in a temporary variable and just multiply it by 2*i*(2*i-1) at each step. Keep in mind that you'll hit a representability/precision wall really quickly at this step.
You also don't need to actually call pow for -1 to the power of i, a simple i%2?1:-1 would suffice. This way it's faster and it won't lose precision as you increase i.
Oh and don't make i float, it's an integer, make it an integer. You're leaking precision a lot as it is, why make it worse..
And to top it all off, you're approximating cos around 0, but are calling it for pi/2. You'll get really high errors doing that.
The Taylor series is for the mathematical cosine function, whose arguments is in radians. So 90 probably doesn't mean what you thought it meant here.
Furthermore, the series requires more terms the longer the argument is from 0. Generally, the number of terms need to be comparable to the size of the argument before you even begin to see the successive terms becoming smaller, and many more than that in order to get convergence. 20 is pitifully few terms to use for x=90.
Another problem is then that you compute the factorial as an int. The factorial function grows very fast -- already for 13! an ordinary C int (on a 32-bit machine) will overflow, so your terms beyond the sixth will be completely wrong anyway.
In fact the factorials and the powers of 90 quickly become too large to be represented even as doubles. If you want any chance of seeing the series converge, you must not compute each term from scratch but derive it from the previous one using a formula such as
nextTerm = - prevTerm * x * x / (2*i-1) / (2*i);

Resources