Recursive algorithm to calculate square root - c

I have a code that calculates the square root of a number the following way:
void f1(int,int);
int main(){
int i=1;
int n;
scanf("%d",&n);
f1(n,i);
getch();
return 0;
}
void f1(int n,int i){
if((n*10000)-(i*i)<=0)
printf("%f",(double)i/100);
else
f1(n,i+1);
}
I don't know why using n*10000 - i*i. Can someone explain this code please?

Lets consider the example n=100. For the first bunch of recursions, we have i=1,2,3,.... Thus, for these calls, we have n*10000 - i*i >= 0. Then at some point we have i=999 and observe that n*10000 - 999*999 >= 0. The next recursive step has i=1000 and we see that n*10000 - 1000*1000 <= 0, so we print (double)i / 100, which is then just 10. As you can see, the result is just the sqare root of n=100.
In general, the smallest number i/100 satisfying n*10000 - i*i <= 0 is "quite close" to the sqare root of n, because of the following:
sqrt(n*10000) = sqrt(n)*sqrt(10000) = sqrt(n)*100
And we have:
n*10000 - i*i <= 0 | +i*i
n*10000 <= i*i | sqrt both sides
sqrt(n)*100 <= i | /100
sqrt(n) <= i/100
Thus, we are looking for the smallest number i/100 that is greater or equal to sqrt(n) and use this number as an approximation for sqrt(n).

you call the function with n and i,
now as long as i*i is smaller than n * 10000 you increase your i.
if your i*i is bigger than n * 10000 you print i / 100
eg: you call function with f1(1,1):
1*10000 >= 1*1 --> f1(1,2);
1*10000 >= 2*2 --> f1(1,3);
1*10000 >= 3*3 --> f1(1,4);
....
1*10000 >= 99*99 ->f1(1,100);
1*10000 <= 100*100 --> printf("%f",i/100.0); which gives: 1
EDIT: another example, you look for the sqare root of 8: f1(8,1);
8*10000 >= 1*1 --> f1(8,2);
8*10000 >= 2*2 --> f1(8,3);
1*10000 >= 3*3 --> f1(8,4);
....
8*10000 >= 282*282 ->f1(8,283);
8*10000 <= 283*283 --> printf("%f",i/100.0); which gives: 2.83
and 2.83 * 2.83 = 8.0089
EDIT: you may ask why n*10000, its because the calculation error gets smaller, eg: if you use n*100 and i/10 in the sqrt of 8 example you get
8*100 <= 29*29 --> 2.9
2.9 * 2.9 = 8.41 which is not good as 2.83 in the other example

That is just to add some precision.
void f1(int n,int i){
printf("value of i is=%d \n",i);
if(n-i*i<=0)
printf("%f",i);
else
f1(n,i+1);
}
this code will work for only perfect square numbers.
void f1(int n,int i){
printf("value of i is=%d \n",i);
if((n*100)-(i*i)<=0)
printf("%f",(double)i/10);
else
f1(n,i+1);
}
this code will work for all numbers but will give result for just one digit after floating point.
void f1(int n,int i){
printf("value of i is=%d \n",i);
if((n*10000)-(i*i)<=0)
printf("%f",(double)i/100);
else
f1(n,i+1);
}
this is your code which gives 2 digit point precision after floating point.
so that (n*10000)-(i*i) is necessary as per your requirement.
if you want to find for only perfect you can use first code too.

Consider this function:
void f1(int n,int i){
if((n)-(i*i)<=0)
printf("%f",i);
else
f1(n,i+1);
}
This function would recursively loop over i until i^2 >=n, it's basically the same as doing this without recursion:
void f1(int n,int i){
int i = 1;
while (i*i < n)
++i;
printf("%f",i);
}
Now the trick with the 10000 is just to add some precision emulated by large integers (note that it might overflow an int faster like that) - you calculate sqrt(100*100*n), which is 100*sqrt(n), so you divide the result by 100. This allows you to get a 2 digit precision.

because it will get the result rounded to two decimals.
for example,
n=10 the result is 3.17.
and if you want to get result rounded to 3 decimals, you can write:
if((n*1000000)-(i*i)<=0)
printf("%f",(double)i/1000);

Related

What should I change so that my arctan(x) approximation can display x=1 and x=-1 properly?

One of my C assignments was it to write an approximation of arctan(x) in the language C. The equation which I should base it on is
arctan(x)=\sum {k=0}^{\infty }(-1)^{k} \tfrac{x^{2k+1}}{2k+1}
In addition x is only defined as -1<=x<=1.
Here is my code.
#include <stdio.h>
#include <math.h>
double main(void) {
double x=1;
double k;
double sum;
double sum_old;
int count;
double pw(double y, double n) {
double i;
double number = 1;
for (i = 0; i < n; i++) {
number *= y;
}
return(number);
}
double fc (double y) {
double i;
double number = 1;
for (i = 1; i <= y; i++){
number *= i;
}
return(number);
}
if(x >= (-1) && x <= 1) {
for(k=0; sum!=sum_old; k++) {
sum_old = sum;
sum += pw((-1), k) * pw(x, (2*k) + 1)/((2*k) + 1);
count++;
printf("%d || %.17lf\n", count, sum);
}
printf("My result is: %.17lf\n",sum);
printf("atan(%f) is: %.17f\n", x, atan(x));
printf("My result minus atan(x) = %.17lf\n", sum - atan(x));
} else {
printf("x is not defined. Please choose an x in the intervall [-1, 1]\n");
}
return 0;
}
It seemingly works fine with every value, except value 1 and -1. If x=1, then the output ends with:
...
7207 || 0.78543285189457468
7208 || 0.78536
Whereas the output should look more like this. In this case x=0.5.
25 || 0.46364760900080587
26 || 0.46364760900080587
My result is: 0.46364760900080587
atan(0.500000) is: 0.46364760900080609
My result minus atan(x) atan(x) = -0.00000000000000022
How can I improve my code so that it can run with x=1 and x=-1.
Thanks in advance.
PS: I use my own created pw() function instead of pow(), because I wanted to bybass the restriction of not using pow() as we didn't had that in our lectures yet.
PPS: I'd appreciate any advice as to how to improve my code.
In each iteration, you add (-1)k • x2k+1 / (2k+1), and you stop when there is no change to the sum.
If this were calculated with ideal arithmetic (exact, infinitely precise arithmetic), it would never stop for non-zero x, since you are always changing the sum. When calculating with fixed-precision arithmetic, it stops when the term is so small it does not change the sum because of the limited precision.
When |x| is less than one by any significant amount, this comes quickly because x2k+1 gets smaller. When |x| is one, the term becomes just 1 / (2k+1), which gets smaller very slowly. Not until k is around 253 would the sum stop changing.
You might consider changing your stopping condition to be when sum has not changed from sum_old very much rather than when it has not changed at all.
if(x >= (-1) && x <= 1) {
for(k=0; sum!=sum_old; k++) {
sum_old = sum;
sum += pw((-1), k) * pw(x, (2*k) + 1)/((2*k) + 1);
count++;
printf("%d || %.17lf\n", count, sum);
}
Comparing doubles can be tricky. The conventional way to compare doubles is to test within epsilon. There should be an epsilon value defined somewhere, but for your purposes how many digits are enough to approximate? If you only need like 3 or 4 digits you can instead have
#define EPSILON 0.0001 //make this however precise you need to approximate.
if(x >= (-1) && x <= 1) {
for(k=0; fabs(sum - sum_old) > EPSILON; k++) {
sum_old = sum;
sum += pw((-1), k) * pw(x, (2*k) + 1)/((2*k) + 1);
count++;
printf("%d || %.17lf\n", count, sum);
}
If the issue is that -1,1 iterate too many times either reduce the precision or increase the step per iteration. I am not sure that is what you're asking though, please clarify.
I think the cause of this is for a mathematical reason rather than a programming one.
Away from the little mistakes and adjustments that you should do to your code, putting x = 1 in the infinite series of arctan, is a boundary condition:
In this series, we add a negative value to a positive value then a negative value. This means the sum will be increasing, decreasing, increasing, ... and this will make some difference each iteration. This difference will be smaller until the preciseness of double won't catch it, so the program will stop and give us the value.
But in the sum equation. When we set z = 1 and n goes from 0 to ∞, this will make this term (-1^n) equal to 1 in one time and -1 in the next iteration. Also,
the value of the z-term will be one and the denominator value when n approaches infinity will = ∞ .
So the sum several iterations will be like +1/∞ -1/∞ +1/∞ -1/∞ ... (where ∞ here represents a big number). That way the series will not reach a specific number. This is because z = 1 is a boundary in this equation. And that is causing infinite iterations in your solution without reaching a number.
If you need to calculate arctan(1) I think you should use this formula:
All formulas are from this Wikipedia article.
Here is some modifications that make your code more compact and has less errors:
#include <stdio.h>
#include <math.h>
#define x 0.5 //here x is much easier to change
double pw(double, double); //declaration of the function should be done
int main() { //the default return type of main is int.
double k;
double sum = 0 ; //you should initiate your variables.
double sum_old = 1 ; //=1 only to pass the for condition first time.
//you don't need to define counter here
if(x < -1 || x > 1){
printf("x is not defined. Please choose an x in the interval [-1, 1]\n");
return 0;
}
for(k=0; sum!=sum_old; k++) {
sum_old = sum;
sum += pw((-1), k) * pw(x, (2*k) + 1)/((2*k) + 1);
printf("%.0f || %.17lf\n", k, sum);
}
printf("My result is: %.17lf\n",sum);
printf("atan(%f) is: %.17f\n", x, atan(x));
printf("My result minus atan(x) = %.17lf\n", sum - atan(x));
return 0;
}
double pw(double y, double n) { //functions should be declared out of the main function
double i;
double number = 1;
for (i = 0; i < n; i++) {
number *= y;
}
return(number);
}
double fc (double y) {
double i;
double number = 1;
for (i = 1; i <= y; i++){
number *= i;
}
return(number);
}

C Code For loop with nested If; modulus and sqrt issue

So, I am trying to get this C code to work. It compiles, but produces incorrect outputs. It should list all pefect square numbers between 1 and a chosen value.
It is doing something wrong, and after alot of trial and error i think the issue is with the modulus operation...like its truncating early or doing some other strange thing.
// C Code
/*This program will identify all square numbers between one and a chosen integer*/
#include <stdio.h>
#include <math.h>
int main(){
int i, upper, square_int;
float square;
printf("This program will identify all square numbers between one and a chosen integer");
printf("Please enter the upper limit integer:");
scanf("%d", &upper);
upper = 13; /*scanf is the primary integer input method; this is here just to test it on codepad*/
for (i = 1; i<= upper; ++i) /*i want to run through all integers between 1 and the value of upper*/
{
square = sqrt(i); /* calc square root for each value of i */
square_int = square; /* change the root from float to int type*/
if (i % (int)square_int == 0) /*check if i divided by root leaves no remainder*/
printf("%d\n", i); /*print 'em*/
}
printf("This completes the list of perfect squares between 1 and %d",upper);
return 0; /*End program*/
}
The output on codepad is:
This program will identify all square numbers between one and a chosen integerPlease enter the upper limit integer:1
2
3
4
6
8
9
12
This completes the list of perfect squares between 1 and 13
Which is of course wrong. I expect to get 1, 2, 4 and 9 back. Can anyone point out my screw up here?
Here is a simpler algorithm
int i = 1;
while (i*i < upper)
{
printf("%d\n", i*i);
++i;
}
Another method is computing the square root, convert it to int, and compare the numbers.
for (i = 1; i <= upper; ++i)
{
square = sqrt(i);
square_int = square;
if (square == (float)square_int)
printf("%d\n", i );
}
Your modulo operation is incorrect. In case of i = 6 square_int will become 2 and thus i % (int)square_int is equal to 6 % 2 which leads to 0.
You could check if square_int * square_int == i instead.
You says you expect to get 1, 2, 4, 9 which means you don't expect to get 3.
Let's see with i == 3:
sqrt(3) == 1.732051
(int) 1.732051 == 1
3 % 1 == 0.
Which means it actually does what it is expected to do but it will not check if a number is a square.
A simple algorithm to check if the number is a square is to do:
sqrt_int = sqrt(i) + 0.5;
if (square_int * square_int == i)
printf("%d\n", i);

Sum of Digits using recursion in C

For our activity today, we were tasked to make using recursion with the sum of digits. I already made this program:
int main()
{
int num = 0, sum;
printf("Enter an integer: ");
scanf("%d",&num);
//counter=1;
for ( sum=0; num>0;)
{
sum = sum + num % 10;
num = num /10;
}
printf("Sum = %d", sum);
getch();
return 0;
}
Our teacher added "Input and output must be done in the main() function." Am doing the right thing? Or am I missing something in my code?
To do recursion, create a function that recurses rather than using a for loop.
int SumDigits(int i) {
if (i < 10) {
return i;
}
else {
return i%10 + SumDigits(i/10);
}
}
scanf("%d", &i);
printf("%d\n", SumDigits(i));
What you have there is an iterative solution, not a recursive one.
Recursion involves defining the problems in terms of a simpler version of the problem, all the time working towards a fixed end point.
The fixed end point in this case is any number less than 10, for which the value is that digit.
The transition to a simpler case (for numbers greater than 9) is simply to add the least significant digit to the result of the number divided by ten (integer division).
Since it's classwork, pseudo-code only I'm afraid.
def digitSum (n):
if n < 10:
return n
return (n % 10) + digitSum (n / 10)
If you follow that for the number 314, you'll see what happens.
At recursion level one, n == 314 so it calculates 314 % 10 to get 4 and calls digitSum(31).
At recursion level two, n == 31 so it calculates 31 % 10 to get 1 and calls digitSum(3).
At recursion level three, n == 3 so it just returns 3
Back up to level two, that's added to the remembered 1 and returned as 4.
Back up to level one, that's added to the remembered 4 and returned as 8.
Hence you end up with the digit sum of 8 for the number 314.

Problem in proper divisor algo

I wrote two algos to get the sum of the proper divisors of a given number,to find perfect number or abundant number.
long sum_divisors_1(int a)
{
int i, t;
long sum = 1;
for (i = 2, t = sqrt(a); i < t + 1; i++) {
if (a % i == 0) {
sum += i;
sum += a / i;
}
}
if (a % t == 0)
sum -= t;
return sum;
}
long sum_divisors_2(int a)
{
int i, sum;
sum = 0;
for (i = 1; i < (int) (a / 2 + 1); i++) {
if (a % i == 0)
sum += i;
}
return sum;
}
And I think they are both correct and the first one is faster. But I can only get the correct result from the second algo. Other parts of the code are the same.
Any suggestions? And how the proper divisors are found in real industrial programming?
Thanks in advance.
Your problem lies here:
if (a % t == 0)
sum -= t;
Since you're casting t to an int from a floating point, it will round down to an integer value. This also assumes that t is the actual square root when it isn't. This will evaluate to true when a number has factors x & x+1 (the unit test I posted as well fails when i = 6 because it's square root is 2.45 and 2 is a factor).
The check really should be:
if (t*t == a)
sum -= t;
This is an old question but I was browsing.
There's a much faster algorithm to find the sum of proper divisors.
Find the prime factors of a number using Sieve of Eratosthenes (or Atkin). With wheel factorisation the first 1m prime numbers will take maybe 30ms.
Then the sum of all divisors is
For each n
sum += (n ^ (m+1) - 1) / (n-1)
where n is the factor, m is the power of that factor.
Eg for 220
2^2 5 11 are the factors
So it's sum of
2 ^ (2+1) - 1 / 1 *
5 ^ (1+1) - 1 / 4 *
11 ^ (1+1) - 1 / 10
= 7 * 6 * 12
= 504
This is the sum of ALL divisors, so just subtract N
504-220 = 284
This should be a lot faster than trying all the numbers, especially if you precalculate the sieve and reuse it.
Here's a simple unit test I wrote in C# that will quickly invalidate #1 given #2 is correct:
for(int i = 4; i < 28124; i++)
{
Assert.AreEqual(sum_divisors_2(i), sum_divisors_1(i), "Failed when i = {0}", i);
}
Too big for a comment...
Templatetypedef solved your problem; however the fastest possible way to compute the prime factors is to precompute all the prime factors up to sqrt(MAX_INT) with Eratostene sieve, store it into an array and then use it to factorize the number a. This is really really really much faster.

Generating random numbers from -n to n in C

I want to generate random numbers from -n to n excluding 0. Can someone provide me the code in C? How to exclude 0?
One idea might be to generate a random number x in the range [1,2n], inclusive. Then return -(x - n) for x larger than n, else just return x.
This should work:
int my_random(int n)
{
const int x = 1 + rand() / (RAND_MAX / (2 * n) + 1);
return x > n ? -(x - n) : x;
}
See the comp.lang.c FAQ for more information about how to use rand() safely; it explains the above usage.
The simplest thing I can suggest to do is to generate a Random number between 0 and 2n and then to do the math trick:
result= n - randomNumber
Although 0 might be very unlikely you can check for that using an If and redo the random number generation.
int random(int N)
{
int x;
do{
x=rand()%(N*2+1)-N;
}while(x==0);
return x;
}
It chooses a number from -N to N, but keeps on doing it if it is 0.
An alternative, as suggested in the comments, generates a number between -N and N-1 and increments it if its positive or 0:
int random(int N)
{
int x;
x=rand()%(N*2)-N;
if(x>=0) x++;
return x;
}

Resources