-3

EDITED TO BE REOPENED

People, how are you doing? So, I am trying to atribute the value 0.000010 to a variable, but it becomes a very huge number, and it shouldn't be the case of overflow, due to the type. And it is important to really be 0.000010, because it is used into a condition.

In the code below, it is the varibale dif. During debug, as double, 0.000010 becomes 4.571853192736056e-315. As float, it becomes 9.99999975e-06. If I print it, after atribution, it giver me the right value (0.000010), but debug shows me thos other things.

EDIT TO HELP COMPREHENSION:

What am I supposed to do? I have a PI value calculates as the Gregory-Leibniz series (Pi = 4 -4/3 + 4/5 - 4/7 +...). Each operation (-4/3 and + 4/5, for example) are iteractions. I need to aproximate this Pi to the constant M_PI, from math.h library with a maximum difference of X (a number entered by the user). For exemple, it is necessary 100002 iteractions in the serie to aproximate Pi and M_PI with a difference of 0.000010. So, in this exemple, the user chose dif = 0.000010 and got 100002 iteractions.

The problem, as I said, is that the variable dif (as double or float) can get to be 0.000010 (DEBUG IMAGES AFTER THE CODE).

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
long int n = 0, iteractions = 0;
float Pi1 = 4.0, Pi2 = 0.0, sub = 0.0, sum = 0.0;
double dif = 0.0;

printf("Type the difference to be observed: ");
scanf("%f", &dif);

Pi1 = 4;
sub = Pi1 - M_PI;

for(n=1; sub >= dif; n++){
    Pi2 = (pow(-1,n)*4)/(2*n + 1);
    sum = Pi1 + Pi2;
    Pi1 = sum;
    sub = Pi1 - M_PI;
    iteractions = iteractions + 1;

   }
   printf("Iteractions: %ld \n", iteractions);
   return 0;
}

Image:

Error as double

  • 2
    What specifically is it "becoming"? – Carcigenicate Aug 12 '20 at 18:49
  • 1
    In general you should avoid using `float`. If you need to use floating point, use `double` to get more precision. – Barmar Aug 12 '20 at 18:52
  • I presume you're talking about the value scanned into variable `diferenca`, but I don't see what makes you think that value is incorrect. – John Bollinger Aug 12 '20 at 18:54
  • Prefer `double` when using floating-point values. – pmg Aug 12 '20 at 18:55
  • You never even print `diferenca`, how do you know it has become a huge number? – Barmar Aug 12 '20 at 18:55
  • 1
    Edit the question to provide a [mre]. – Eric Postpischil Aug 12 '20 at 18:56
  • It is the varibale `diferenca`. During debug, as `double`, 0.000010 becomes 4.571853192736056e-315. As `float`, it becomes 9.99999975e-06. If I print it, after atribution, it giver me the right value (0.000010), but debug shows me thos other things. – Everson Elias Gonalves de Oliv Aug 12 '20 at 19:05
  • Nothing whatever is wrong with the data, then. The value your debugger presents when you ask it to interpret `diferenca` as a `double` is irrelevant, because it is not a `double`. The value you get when you have the debugger interpret it as a `float` is the closest representable `float` value to your desired number. If you printed it with `printf("%8.6f\n", diferenca)` then "0.000010" would be the result. – John Bollinger Aug 12 '20 at 19:09
  • See: [Is floating-point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – John Bollinger Aug 12 '20 at 19:10
  • While you're at it, change `pow(-1,n)` to `((n&1)?-1:1)`, and the 4 to 4.0 so it will do the calculation in double. – Lee Daniel Crocker Aug 12 '20 at 19:54
  • @Everson, Curious, why was `float` used for `Pi1, Pi2` instead of `double` or `long double`? – chux - Reinstate Monica Aug 12 '20 at 20:15
  • `double dif = 0.0; ... scanf("%f", &dif);` --> enable all warnings to see why this is bad. – chux - Reinstate Monica Aug 12 '20 at 20:16
  • 1
    I see that you are trying to have the question reopened, @EversonEliasGonalvesdeOliv. I am not wholly satisfied by the original closure reason, but I would certainly have closed it as a dupe of the "Is floating-point math broken?" question that I linked if I had not been preempted. DO read my comment immediately preceding that link. Nothing is wrong. – John Bollinger Aug 12 '20 at 20:42
  • 4.571853192736056e-315 is not a large number. “e-315” means “multiplied by 10 to the power of −315”. That is a very small number. – Eric Postpischil Aug 12 '20 at 21:20

4 Answers4

2

As Carcigenicate asked: What specifically is "it"? What is "it" "becoming"?

I suspect maybe you mean "iteracao" (because it's the only think you're printing), and I suspect maybe it's "huge" because the loop isn't behaving as you expect.

In any case:

  1. Please read this article:

https://floating-point-gui.de/

What Every Programmer Should Know About Floating-Point Arithmetic

or

Why don’t my numbers add up?

  1. Please update your post, clarifying exactly what the problem is, where in your code it's occurring, and what you "expected" vs. what you're seeing.
paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • I suppose the OP means `diferenca`, because it has type `float` and is used in a condition, and because that seems to fit with the supposed input value and the apparent purpose of the program. It is unclear what makes them think that its value is wrong. – John Bollinger Aug 12 '20 at 19:05
  • @Everson Elias Gonalves de Oliv: After seeing your edits: 1) The advice given remains: please consider changing all "float" to "double". 2) Nevertheless, you clarified your problem - thank you. 3) You also stated the END RESULT IS AS EXPECTED, correct? 4) So the *ONLY* problem is that the CodeBlocks debugger is showing unexpected intermediate results for variable `dif`, correct? 5) That's a CodeBlocks debugger issue :( Maybe it'll change after you declare everything "double". Or if you compile with "no optimization" before debugging. Try asking http://forums.codeblocks.org/ – paulsm4 Aug 12 '20 at 20:31
  • 1
    Apparently it's a PEBKAC issue, not a debugger issue. The OP's latest comment on the question indicates that the debugger is reporting the value that should be expected, but in a form and with enough precision that they do not recognize it as such. – John Bollinger Aug 12 '20 at 20:36
  • @John Bollinger - agreed. I still recommend 1) change to "double", 2) read https://floating-point-gui.de/ ... and 3) ALSO read https://www.geeksforgeeks.org/exponential-notation-decimal-number/ – paulsm4 Aug 12 '20 at 20:41
2

The precsion of a float is about 7 digits. You are calculating pi 3.... and want to get to within a difference of 0.000010. This is right at the limit of what a float can represent. Switching to double will give you close to 15 digits of precision.

stark
  • 12,615
  • 3
  • 33
  • 50
2

You're using the wrong format specifier for scanf:

double dif = 0.0;

printf("Type the difference to be observed: ");
scanf("%f", &dif);

The %f format specifier expects a float *, but you're passing in a double *. These point to datatypes of different sizes and different representations. Using the wrong format specifier leads to undefined behavior which is why you're getting the wrong value.

To read a double, use %lf:

scanf("%lf", &dif);

Also, the value 0.000010 cannot be represented exactly in binary floating point, so even with this fix you'll see a value that is slightly larger or slightly smaller than the entered value.

dbush
  • 205,898
  • 23
  • 218
  • 273
0

people, thank you for the help. The right code is this one bellow.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
int n = 0, iteractions = 1;
double Pi1 = 4.0, serie = 0.0, sub = 0.0, sum = 0.0;
double dif = 0.0;

printf("Type the difference to be observed: ");
scanf("%lf", &dif);

Pi1 = 4;
sub = Pi1 - M_PI;

for(n=1; sub >= dif; n++){

    serie = (pow(-1,n)*4)/(double)(2*n + 1);

    iteractions = iteractions + 1;

    sum = Pi1 + serie;

    Pi1 = sum;

    sub = Pi1 - M_PI;

    if(sub < 0){
        sub = -1 * sub;
    }

}

printf("Iteractions: %d \n", iteractions);

return 0;
}