floating point rounding errors - c

The output is
x=1000300 y=1000000, z=1000300
I can understand how I got x and z but c's y's output makes no sense.
#include <stdio.h>
int main()
{ int i=0;
float a = 100;
a = a*a*a*a*a;
float c = 3;
float x = 1000000*c + a;
float y = a;
float z = 0;
for (i=0; i<1000000; i++)
{ y += c;
z += c;
}
z += a;
x /= 10000;
y /= 10000;
z /= 10000;
printf("x=%.0f y=%.0f, z=%.0f\n", x, y, z);
}

The value in y starts out at 1E10 (from the assignment to a). You add 3 to this a million times.
The trouble is that a float has at most 7 significant decimal digits, so you effectively do not change y each time, hence the result divided by 10,000 is 10,000,000 1,000,000 as displayed.
If you coded it with double, you would see more nearly the result you expect.

Related

Find Mystery Nums M/N

I am pretty sure I got this right just want to make sure though... In the following code, we have omitted the definitions of constants M and N
here are the two functions in question arith and optarith:
#define M /* Mystery number 1 */
#define N /* Mystery number 2 */
unsigned int arith(unsigned int x, unsigned int y){
unsigned int result = 0;
result = x * M + y/N;
return result;
}
We compiled this code for particular values of M and N. The compiler optimized the multiplication and
division. The following is a translation of the generated machine code back into C:
unsigned int optarith(unsigned int x, unsigned int y){
unsigned int t = 3 * x;
x <<= 6;
x -= 2 * t;
y >>= 4;
y = y/3;
return x + y;
}
so here's my work
so to find value M for the operation M * x
x <<= 6; // same as x = x * 64
x-= 2 * t; //same as x = x - 2 * (3 * x)
so basically x = 64x - 6x which is just 58x therefore M = 58
and to find the value N for operation y/N
y >>= 4; same as y = y/16;
y = y/3; same as y = (y/16)/3;
that makes y/48 so N = 48
Did I do this correctly?

Write c code to evaluate the integral between 0 and y of (x^2)(e^-x^2)dx using Simpson's rule (use a fixed number of 20,000 steps)

Second part of Q: Then solve the integral between 0 and y of (x^2)(e^(-x^2))dx=0.1 for y using bracketing and bisection.
Here's what I have done so far:
#include <stdio.h>
#include <math.h>
double f(double x, double y);
int main(void) {
int i, steps;
double a, b, y, h, m, lower, upper, x, simp, val;
/*
* Integrate (x^2)(e^(-x^2)) from 0 to y
*/
steps = 20000;
a = 0;
b = y;
h= (b-a)/steps;
/*
* now apply Simpson's rule. Note that the steps should be even.
*/
simp = -f(a, y);
x = a;
for (i =0; i < steps; i += 2) {
simp += 2.0*f(x,y)+4.0*f(x+h, y);
x += 2*h;
}
simp += f(b, y);
simp *= h/3.0;
/*
* print out the answer
*/
printf("The integral from 0 to y with respect to x by Simpson's Rule is %f\n", simp);
/*
* Now we need to bracket and bisect to find y
*/
lower = 0;
/*
* Lower bound is from turning point
*/
upper = 100;
/*
*Upper value given.
*/
while (upper - lower > 10E-10){
m = (lower + upper)/2;
val = f(m, y);
if (val >=0)
upper = m;
if (val <=0)
lower = m;
}
m = (lower + upper)/2;
printf("The value for y is: %lf\n", m);
return 0;
}
double f(double x, double y) {
return pow(x,2)*exp(pow(-x,2))-0.1;
}
Output: The integral from 0 to y with respect to x by Simpson's Rule is -0.000000
The value for y is: 0.302120
It runs but doesn't do exactly what I need it to do. I need to be able to continue working with the integral once I've used 0 and y as the limits. I can't do this. Then continue on and solve for y. It gives me a value for y but is not the same one I get if i solve using online calculators. Also, the output gave zero for the integral even when I changed the equation to be integrated to x^2. Can anyone help explain in as simple terms as possible?

Integration using the Trapezium Rule in C giving wrong answer for certain values

I've written some code to Integrate the function 5x^4 + 4x^3 + 3x^2 + 2x + 1.
#include<stdio.h>
#include<math.h>
float func(float x){
float a;
a = 5*pow(x,4) + 4*pow(x,3) + 3*pow(x,2) + 2*x +1;
return a;
}
int main(){
float numberOfXValues;
float a = 0; //lower limit
float b = 1; //upper limit
float numberOfStrips;
float stripSize;
float finalAnswer;
float sumFirstAndLast; //summation of first and last x value
while(1){
printf("Input number of X values:");
scanf("%f", &numberOfXValues);
numberOfStrips = numberOfXValues - 1;
stripSize = (b - a)/(numberOfStrips);
sumFirstAndLast = 0.5*func(a) + 0.5*func(b);
for (float z = stripSize; z < b; z += stripSize ){
sumFirstAndLast += func(z);
}
finalAnswer = sumFirstAndLast * stripSize;
printf("%f\n", finalAnswer);
}
return 0;
}
And it works for the majority of values, but the output for 13 and 20 is giving the wrong answer. I've looked through it a few times but can't see what could be causing this.
Input number of X values:10
5.039070
Input number of X values:11
5.031651
Input number of X values:12
5.026160
Input number of X values:13
6.271982
Input number of X values:14
5.018732
Input number of X values:15
5.016153
Input number of X values:16
5.014071
Input number of X values:17
5.012367
Input number of X values:18
5.010955
Input number of X values:19
5.009773
Input number of X values:20
5.798243
Input number of X values:21
5.007917
The problem is that in the exit condition of the inner loop, you compare two floating point numbers. After numberOfStrips iterations, it's not guaranteed that z == b because of floating point accuracy. It's entirely possible that z < b or z > b. In the z < b case, the loop it executed another time.
You should make numberOfStrips an integer and rewrite the loop like this:
float z = stripSize;
for (int i = 1; i < numberOfStrips; i++) {
sumFirstAndLast += func(z);
z += stripSize;
}
At a first glance this looks to precision and rounding issues of float.
Therefore change float to double.
For example on my machine I get 6.271982 for an input of 10 when using float while I get 5.021983 as result when using double.
Moreover you should use an epsilon in floating point comparisons.
Placing the line:
printf("%f, %d\n", z, z < b);
Inside the for loop will print the z values each iteration along with the loop condition result. The last output of this will be:
1.000000, 1
Which is pointing that we have already reached the right limit, but still performing the loop body. Literally it is thinking that 1.000 < 1.000. It can happen when working with float numbers, so in order to prevent it, consider looping on some integer number (numberOfXValues for example).

Not sure why C prints out NaN

I was coding up a short program to compute right endpoints for a given graph (not shown here), so to avoid tedious computation, I decided to write up a short program to do the work for me. Yet my C program just prints out nan. I am very rusty on C, but I am not sure why I am getting NaN.
#include <stdio.h>
int main(void) {
int x;
float y, z;
for (x = 0; x <= 8; x++) {
y += 10.0 - (12.0 + (float)x) / 4.0;
printf("%f\n", y);
}
z = 0.5 * y;
printf("%f\n", z);
return 0;
}
y = 10.0 - (12.0 + (float)x) / 4.0;
Followed by
y = y+1;
This makes sense else you have y uninitialized which leads to undefined behavior because the value of y is undeterminate.
During declaration you can initialize y and use += operator.
Like
float y = 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 ...

Resources