Sam
Sam

Reputation: 1

C: Why do not get the last line of my output?

The question I am working on asks me to write code that prints each value from -1 to 1 inclusive, incremented by a value of 0.01 to solve the mathematical function f(x) = x^2 + 4 (to 4 decimal places).

example:

f(-1.00) = 5.0000
f(-0.99) = 4.9801
...
f(1.00) = 5.0000

Problem:

I do not get the last line of the code: f(1.00) = 5.0000. My question is how do I modify my program so that it does appear, and can you also explain why it does not appear in the first place, please?

Code:

Below is my code. It is printing out every value of y when x is between 0 and 1, except for f(1.00) = 5.0000...

double numberForQ4 = -1.00; 
double valueOfY = 0; 

for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01 ) { 
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.2f) = %.4f \n", numberForQ4, valueOfY );
}

Upvotes: 0

Views: 441

Answers (6)

Hasan
Hasan

Reputation: 1298

The reason that you dont get the last value is about the variable type you are using (double). When you increment your index variable by 0.1 it is not as precise as you expected, You can observe that values with the code below.

    int main()
{
    double numberForQ4 = -1.00; 
    double valueOfY = 0; 

    for ( ; numberForQ4 <= 1.00; numberForQ4 += 0.01) {
    printf("numForQ4 =  %.5f \n", &numberForQ4);
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.2f) = %.4f \n", numberForQ4, valueOfY );
    }

    return 0;
}

As you will notice the last call is made with numberForQ4= 0.98. This is why you are not able to calculate the value with 1.00.

When you update your code line where you initilize variables to as shown below, you will get the correct output as I did in the online compiler. 



int main()
{
    float numberForQ4 = 1.00; 
    double valueOfY = 0; 

    for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.0100 ) {
    printf("numForQ4 =  %.5f\n", &numberForQ4);
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.2f) = %.4f \n", numberForQ4, valueOfY );
    }

    return 0;
}

Upvotes: 1

chux
chux

Reputation: 153348

Why do not get the last line of my output?

Floating point math has peculiarities since 0.01 is not exactly representable as a double given it encodes as some binary fraction. In OP's case, something just higher or lower than 0.01 and subsequent math makes for just slightly unexpected results.

how do I modify my program

Instead, iterate using an integer.

// for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01 ) { 
for ( int i = -100; i <= 100; i++ ) { 
  numberForQ4 = i/100.0;
  ...

Tip: iteration loops are best coded using integers.


can you also explain why it does not appear in the first place, please?

Try your original code again and use enough precision to see why.

printf( ".01 = %.21f\n", 0.01);
for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01 ) { 
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.21f) = %.21f \n", numberForQ4, valueOfY );
}

Upvotes: 4

4386427
4386427

Reputation: 44274

If you make this little change:

for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01 ) { 
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.20f) = %.4f \n", numberForQ4, valueOfY );
         //       ^ 20 instead of 2
}

You will get output like:

f(-1.00000000000000000000) = 5.0000 
f(-0.98999999999999999112) = 4.9801 
f(-0.97999999999999998224) = 4.9604 
f(-0.96999999999999997335) = 4.9409 
. . .
. . .
f(0.97000000000000141664) = 4.9409 
f(0.98000000000000142553) = 4.9604 
f(0.99000000000000143441) = 4.9801 

As you can see, the rounding error of the double causes the "last" iteration to be skipped. That is: Adding 0.1 to 0.99000000000000143441 will give something greater than 1.0 causing the loop to end.

For a way to solve this, see the answer by @chux: https://stackoverflow.com/a/53736875/4386427

Upvotes: 3

Atheel Massalha
Atheel Massalha

Reputation: 464

change to:

double numberForQ4; 
double valueOfY = 0; 
int i=0;


for ( numberForQ4 = -1.00; i <= 200; numberForQ4 += 0.01 , i++ ) { 
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.2f) = %.4f \n", numberForQ4, valueOfY );
}

you old loop start from 1.00 and ends on 1.00, so it will do only one iteration. the condetion for the loop to stop is !(numberForQ4 <= 1.00), and if you start from 1.00, in the next iteration numberForQ4 will be equal 1.01 (numberForQ4 > 1.00)

you counter is not precise enough, best solution as mentioned in comments is to use integer counter.

Upvotes: 0

ShivYaragatti
ShivYaragatti

Reputation: 398

increment is 0.01 but it may not adding exactly 0.01 to numberForQ4 due to the way floating/double precision works( since 0.01 can't be sure it is float or double here since double is just more precisioin of float).

append f at end of the value like below, would help

numberForQ4 += 0.01f

for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01f ) {

following is good read about these rounding of errors http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)FloatingPoint.html

Upvotes: 0

sjdm
sjdm

Reputation: 589

double numberForQ4 = 1.00; 
double valueOfY = 0; 

for ( numberForQ4 = -1.00; numberForQ4 <= 1.00; numberForQ4 += 0.01 ) { 
    valueOfY = numberForQ4 * numberForQ4 + 4; 
    printf( "f(%.2f) = %.4f \n", numberForQ4, valueOfY );
}

Im guessing you meant to put -1.00 or 0 in the assignment of numberForQ4

Upvotes: 0

Related Questions