Reputation: 1
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
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
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
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
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
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
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