find square root with Newton using integers - c

In this program, I'm trying to calculate the square root with the newton equation 1/2(x+a/x) just using integers. So if I repeat this equation at least 10 times, it should divide the number by 1000 and give an approximate value of the square root of a/1000. This is the code:
int main (){
int32_t a, x; //integers a and x
float root;
do{
scanf ("%d", &a); // get value of a from the user
if (a < 1000 ){ // if chosen number is less than 1000 the programm ends.
break;
}
x = ((float) a / 1000); //starting value of x is a / 1000;
for (int i = 0; i < 50;i++)
{
root = ((float) x * (float) x + a/1000) / ((float)2*x); // convert int to float //through casting
x = (float)root; // refresh the value of x to be the root of the last value.
}
printf ("%f\n", (float)root);
}while (1);
return 0;
}
so if I calculate the square root of 2000, it should give back the square root of 2(1.414..), but it just gives an approximate value: 1.50000
How can I correct this using integers and casting them with float?
thanks

#include <stdlib.h>
#include <stdio.h>
int main (int argc, char * *argv, char * *envp) {
int32_t a, x; //integers a and x
float root;
do {
scanf ("%d", &a); // get value of a from the user
if (a < 1000) { // if chosen number is less than 1000 the program ends.
break;
}
x = (int32_t)((float) a / 1000.0f); //starting value of x is a / 1000;
for (int i = 0; i < 1000; i++) {
// Fixed formula based on (x+a/x)/2
root = ((float)x + (((float)a) / (float)x)) / 2.0f;
//Below, wrong old formula
//root = ((float) x * (float) x + a / 1000) / ((float) 2 * x); // convert int to float //through casting
x = (int32_t) root; // refresh the value of x to be the root of the last value.
}
printf ("%f\n", root);
} while (1);
return (EXIT_SUCCESS);
}

The iterates of x = (x + a / x) / 2 for a = 2000000 and x0 = 1000 (all integer variables) are 1500, 1416 and 1414. Then 200000000 gives 14142 and so on.

Related

Calculate the value of 𝜋 from the infinite series in c

I am trying to make a C program that calculates the value of Pi from the infinite series, aka Leibniz series, and display it to the user. My problem is that I need to display a special message that appears when the program hits the first 3.14, and the first 3.141. That special message should include in which iteration of the loop did the the number become 3.14 and 3.141. I am not lazy so a found a way to make the infinite series but the second part I couldn't figure out, so what should I add to my code to make it display the special message?
#include <stdio.h>
int main(void) {
int i, den; // denominator and counter
double pi = 4;
for (i = 0; i < 10000; i++) {
den = i * 2 + 3;
// (4 - 4/3 + 4/5 -4/7 + 4/9 -......)
if (i % 2 == 0) {
pi = pi - (4.0 / den);
}
else {
pi = pi + (4.0 / den);
}
printf("pi = %lf\n", pi);
}
}
Here's a possible solution:
#include<stdio.h>
#include <math.h>
int
main (void)
{
int i, den; //denominator and counter
int prec = 0;
double pi = 4;
for (i = 0; i < 10000; i++)
{
den = i * 2 + 3;
//(4 - 4/3 + 4/5 -4/7 + 4/9 -......)
if (i % 2 == 0)
pi -= 4.0 / den;
else
pi += 4.0 / den;
//printf ("pi = %lf\n", pi);
if (prec < 1 && trunc (100 * pi) == 314)
{
printf ("Found 3.14 at iteration %d\n", i);
prec++;
}
if (prec < 2 && (int)trunc (1000 * pi) == 3141)
{
printf ("Found 3.141 at iteration %d\n", i);
prec++;
}
}
}
The output is:
pi = 2.666667
pi = 3.466667
pi = 2.895238
...
pi = 3.150140
pi = 3.133118
pi = 3.149996
Found 3.14 at iteration 117
...
pi = 3.141000
pi = 3.142185
pi = 3.141000
Found 3.141 at iteration 1686
...
Here is a version that compares the first n digits of a double cmp_n(). Variables use minimal scope. The variable oracle holds the truncated pi to n decimals. The values of oracle must be stored in ascending order. I tweaked the pi formula to be a bit more compact format.
#include <math.h>
#include <stdio.h>
int cmp_n(double d1, double d2, size_t n) {
return fabs(trunc(pow(10, n) * d1) - trunc(pow(10, n) * d2)) < 1.0;
}
int main() {
double pi = 4;
size_t o = 0;
struct {
double pi[;
size_t n;
} oracle[] = {
{ 3.14, 2 },
{ 3.141, 3 }
};
for (int i = 0; i < 10000; i++) {
int den = i * 2 + 3;
//(4 - 4/3 + 4/5 -4/7 + 4/9 -......)
pi += ((i % 2) ? 4.0 : -4.0) / den;
int special = 0;
if(
o < sizeof(oracle) / sizeof(*oracle) &&
cmp_n(pi, oracle[o].pi, oracle[o].n)
) {
special = 1;
o++;
}
printf("pi = %.15f%2s\n", pi, special ? "*" : "");
}
}
and the relevant data (with line numbers);
$ ./a.out | nl -v0 | grep '*'
117 pi = 3.149995866593470 *
1686 pi = 3.141000236580159 *
Note: you need to add the "%.15lf" format string other the pi output is rounded. double only gives you about 15 digits, and the cmp_n() scales the number and this may not work as expected as you get close to the precision supported by double.

Reversing last n digits of an Integer in C

I need to write a program that takes 2 digits(X and n) and then prints X with last n digits of X reversed.
For example
Input: 12345 3
Output: 12543
Input: 523 2
Output: 532
I already wrote a control mechanism for checking n is greater or equal than the number of digits of X
For example if inputs are 6343 and 7, program prints that inputs should be changed and takes input again.
My main problem is I couldn't find an algorithm for reversing last n digits. I can reverse any int with this code
int X, r = 0;
printf("Enter a number to reverse\n");
scanf("%d", &n);
while (X != 0)
{
r = r * 10;
r = r + n%10;
X = X/10;
}
printf("Reverse of the number = %d", r);
But I couldn't figure how two reverse just last digits. Can you give me any idea for that?
I couldn't figure how to reverse just last digits
Separate the number using pow(10,n) - see later code.
unsigned reverse_last_digits(unsigned x, unsigned n) {
unsigned pow10 = powu(10, n);
unsigned lower = x%pow10;
unsigned upper = x - lower;
return upper + reverseu(lower, n);
}
Create a loop that extracts the least-significant-digit (%10) and builds up another integer by applying that digit. (y = y*10 + new_digit)
unsigned reverseu(unsigned x, unsigned n) {
unsigned y = 0;
while (n-- > 0) {
y = y*10 + x%10;
x /= 10;
}
return y;
}
For integer type problems, consider integer helper functions and avoid floating point functions like pow() as they may provide only an approximate results. Easy enough to code an integer pow().
unsigned powu(unsigned x, unsigned expo) {
unsigned y = 1;
while (expo > 0) {
if (expo & 1) {
y = x * y;
}
expo >>= 1;
x *= x;
}
return y;
}
Test
int main() {
printf("%u\n", reverse_last_digits(12345, 3));
printf("%u\n", reverse_last_digits(523, 2));
printf("%u\n", reverse_last_digits(42001, 3));
printf("%u\n", reverse_last_digits(1, 2));
}
Output
12543
532
42100
10
Code uses unsigned rather than int to avoid undefined behavior (UB) on int overflow.
It is an easy one.
1. let say the number you want to reverse is curr_number;
2. Now, the places you want to reverse is x;
(remember to verify that x must be less than the number of digit of curr_number);
3. now, just take a temp integer and store curr_number / pow(10,x) ('/' = divide and pow(10,x) is 10 to the power x)
4. now, take a second number temp2, which will store curr_number-(temp * pow(10,x) )
5. reverse this temp2 (using your function)
6. now, answer = (temp * pow(10,x) ) + (temp2) //(note temp2 is reversed)
example with steps:
curr_number = 1234567
places you want to reverse is 3
temp = 1234567 / (10^3) i.e (1234567/1000) = 1234 (because it is int type)
temp2 = 1234567 - (1234*10^3) i.e 1234567 - 1234000 = 567
reverse(567) = 765
answer = (1234 * 10^3) + 765 = 1234765
Create two variables
lastn which stores the last n digits (345)
r which stores the reversed last n digits (543)
Subtract lastn from the original number (12345 - 345 = 12000)
Add r to the above number (12000 + 543 = 12543)
int c = 0; // count number of digits
int original = x;
int lastn = 0;
while (x != 0 && c < n) {
r = r * 10;
r = r + x % 10;
lastn += (x % 10) * pow(10, c);
x = x / 10;
c++;
}
printf("reversed: %d\n", original - lastn + r);
In case you don't have problems using char, you can do this
#include <stdio.h>
#include <string.h>
#define SIZE 10
int main() {
char n[SIZE]; // the Number;
int x; // number of last digits of n to reverse
int len; // number of digits of n
scanf("%s%d", n, &x);
len = strlen(n);
for(int i = 0; i < len; i++) {
i < len - x ? printf("%c", n[i]) : printf("%c", n[2*len -1 - i - x]);
}
return 0;
}
If you want you can make the program more readable by splitting the for in two
for(int i = 0; i < len - x; i++) {
printf("%c", n[i]);
}
for(int i = len-1; i >= len - x; i--) {
printf("%c", n[i]);
}
Note: the program won't work if n > x (i.e. if you want to swap more digits than you got)

How would you use the while statement to find the square root using the while loop

I have to write a program that will find a square root using the while loop. I was given this new_guess = (old_guess + (n / old_guess)) / 2.0; but I dont fully understand what to do with it, this is what I have:
int main(void)
{
double n, x, new_guess, old_guess, value;
printf("Enter a number:");
scanf("%lf", &n);
x = 1.00000;
while (new_guess >= n) {
new_guess = (old_guess + (n / old_guess)) / 2.0;
printf("%10.5lf\n", fabs(new_guess));
}
return 0;
}
x is the initial guess. Im really lost on how to do it. This is C also. I know its really wrong but I really dont understand how to make it start because when I enter a number it just stop right away.
Your program has undefined behavior because both new_guess and old_guess are uninitialized when you enter the loop.
The condition is also incorrect: you should stop when new_guess == old_guess or after a reasonable maximum number of iterations.
Here is a modified version:
#include <math.h>
#include <stdio.h>
int main(void) {
double n, x;
int i;
printf("Enter numbers:");
while (scanf("%lf", &n) == 1 && n >= 0.0) {
x = 1.0;
/* Using a while loop as per the assignment...
* a for loop would be much less error prone.
*/
i = 0;
while (i < 1024) {
double new_guess = (x + (n / x)) / 2.0;
if (new_guess == x)
break;
x = new_guess;
i++;
}
printf("%g: %.17g, %d iterations, diff=%.17g\n",
n, x, i, sqrt(n) - x);
}
return 0;
}
Given the start value, the number of iterations grows with the size of n, exceeding 500 for very large numbers, but usually less than 10 for small numbers. Note also that this algorithm fails for n = 0.0.
Here is a slightly more elaborate method, using the floating point break up and combine functions double frexp(double value, int *exp); and double ldexp(double x, int exp);. These functions do not perform any calculation but allow for a much better starting point, achieving completion in 4 or 5 iterations for most values:
#include <math.h>
#include <stdio.h>
int main(void) {
double n, x;
int i, exp;
printf("Enter a number:");
while (scanf("%lf", &n) == 1 && n >= 0.0) {
if (n == 0) {
x = 0.0;
i = 0;
} else {
frexp(n, &exp);
x = ldexp(1.0, exp / 2);
for (i = 0; i < 1024; i++) {
double new_guess = (x + (n / x)) / 2.0;
if (new_guess == x)
break;
x = new_guess;
}
}
printf("%g: %.17g, %d iterations, diff=%.17g\n",
n, x, i, sqrt(n) - x);
}
return 0;
}

Conveying a formula in C (% is)

So I have to make this formula "y = y / (3/17) - z + x / (a % 2) + PI" in C
I am having a problem with (a%2) as it is returning odd values. ie 1%2 = 0.000001
int assignment7()
{
#define PI 3.14
int a=0,amod2;
double Ny=0,y=0,z=0,x=0;
printf("Enter values for x,y,z and a: ");
scanf("%d%lf%lf%lf",&a,&y,&z,&x);
//printf("%d,%lf,%lf,%lf\n",a,y,z,x);
//amod2=1%2;
//printf("%lf",amod2);
Ny=y/(double)(3/17) - z+x / amod2 + PI;
printf("%lf\n",Ny);
When you say:
printf("%lf",amod2);
the compiler expects amod2 to be a "long float" (aka a double), but you defined it as:
int amod2;
Also your prompt says "x,y,z and a" but you read in the order "a,y,z,x":
printf("Enter values for x,y,z and a: ");
scanf("%d%lf%lf%lf",&a,&y,&z,&x);
that's awkward at best.
EDIT: cleaned up a bit and made some assumptions about order of operations:
#include <stdio.h>
#define PI 3.14
#define DIVSOR (3.0/17.0)
int assignment7 ( void );
int assignment7 ( void ) {
double x = 0.0;
double y = 0.0;
double z = 0.0;
int a = 0;
int amod2;
double Ny;
printf("Enter values for x,y,z and a: ");
scanf("%lf%lf%lf%d",&x,&y,&z,&a);
amod2 = a % 2;
Ny = (y / DIVSOR) - z + (x / amod2) + PI;
printf("%lf\n", Ny);
return 0;
}
int main ( void ) { return assignment7(); }
You don't say what inputs you are giving it, (a test case with inputs and the expected results would be super helpful), but I can point out that x / (a % 2) is going to be infinity when a is 2 or 4 or 6 or ...

Square root in C using Newton-Raphson method

In the following code, I want to replace the termination condition to: if the ratio of guess square and x is close to 1, while loop should terminate. I tried various expressions, but none run the code properly. any suggestion?
# include<stdio.h>
float absolute(float x)
{
if (x < 0)
x = -x;
return x;
}
float square(float x)
{
float guess = 1;
while(absolute(guess*guess - x) >= 0.0001 )
guess = ((x/guess) + guess) / 2;
return guess;
}
int main(void)
{
printf("square root of 2 is %f\n", square(2));
printf("square root of 3 is %f\n", square(3));
return 0;
}
hit the answer: while statement should be like this:
while ( absoluteValue((guess * guess) / x - 1.0) >= 0.0001 )
# include<stdio.h>
double sq_root(double x)
{
double rt = 1, ort = 0;
while(ort!=rt)
{
ort = rt;
rt = ((x/rt) + rt) / 2;
}
return rt;
}
int main(void)
{
int i;
for(i = 2; i<1001; i++) printf("square root of %d is %f\n",i, sq_root(i));
return 0;
}
if the ratio of guess square and x is close to 1
Then why are you subtracting? Use ratio operator:
while(absolute( (guess*guess) / x - 1) >= 0.0001 )
It's possible you can't reach that guess*guess will be enough close to x; imagine e.g. sqrt of 2e38 - every approximation will be no closer than ~1e31 and your exit condition won't ever succeed.
The variant good for all cases is that stopping for this method occur when guess stops to change. So you would write something like
prev_guess = 0; // any initial value is ok
while (guess != prev_guess) {
...
prev_guess = guess;
}
at least it shall work for any IEEE754-compatible implementation not reaching overflow or underflow.
Also you can compare guess and prev_guess for difference (as soon as the goal is usually to match enough accuracy of root, not the value squared back).

Resources