1

So I am new to C, and I mainly use it to make calculators for probability and stuff like that. My current project finds the increase and decrease of 2 values.

The code is:


#include <stdio.h>
//Variables

//Main Area
int
main ()
{
  float num1;
  float num2;
  float num3;
  float num4;
  float answer;
  //Scanning for the first number
  printf ("\n Please Enter the first Value : ");
  scanf ("%f", &num1);
  //scanning for the second number
  printf ("\n Please Enter the second Value : ");
  scanf ("%f", &num2);
  //calculating
  num3 = num1 - num2;
  num4 = num3 / num1;
  answer = num4 * 100;
  //Checking if the answer is an increase or decrease
  if (answer > 0) {
      printf("The answer has been decreasedby: %f\n", answer);
      printf("percent");
  }
  else {
    
      printf("The answer has been increased by: %f\n", answer * -1);
      printf("percent");
  }
  
  
  //Printing the answer
  
 
}


The output:

 Please Enter the first Value: 9                                                                                                                            
 Please Enter the second Value : 90                                                                                            
The answer has been increased and the final value is: 900.000000                                                               
percent

So I set all the values as Floats rather than Ints because Ints only support whole numbers. But when I do get a whole number rather then displaying only the single number with no decimal points, it produces a number with the number and a bunch of zeros after the decimal point. Is there a way to detect if the number Is a whole number and just display that number?

Thanks

  • 1
    Hmmm ... maybe if you compare `x - (int)x` with a small number suits you ... `if (x - (int)x < 0.000000001) /* x is (kinda) a whole number */;` – pmg Jun 29 '20 at 07:00
  • Ok I will try, but again how do I display only the first digits – comicalvery Jun 29 '20 at 07:04
  • 3
    Is this just an output-problem? Did you try `%.2f` or `%.2g` instead of `%f`? – chtz Jun 29 '20 at 07:17
  • When is `x` a whole number? `x = M_PI - 0.14159`? `x = M_PI - 0.1415926535`? `x = M_PI - 0.141592653589793`? `x = M_PI - 0.14159265358979323846`? `x = M_PI - 0.1415926535897932384626433`? – pmg Jun 29 '20 at 07:31
  • Oh, Prefer `double` when dealing with floating-point values. – pmg Jun 29 '20 at 07:34
  • Asking whether a number is a whole number or a float is like asking whether an animal is a dog or a mammal. – n. m. could be an AI Jun 29 '20 at 07:53
  • 1
    Read http://floating-point-gui.de/ – Basile Starynkevitch Jun 29 '20 at 08:13
  • 2
    Edit the question to provide a [mre], including exact input that reproduces the problem and the exact output the program produces. Formatting with `%f` does not normally provide “about thirty 0’s”, and that is not an adequate problem description, especially since the input needed to produce that output is not provided. – Eric Postpischil Jun 29 '20 at 11:14
  • @EricPostpischil To be honest, the description "*about thirty 0's*" was my edit. Before it was "*30 0's*. I changed "30" to "thirty" because of danger of confusion with its output and the 30 would only be a feeling since it shouldn't in fact output thirty digits of the fraction part. This is pedantry but shall we/I remove the "*about*"? – RobertS supports Monica Cellio Jun 29 '20 at 13:15
  • Hi, thanks for all the answers. @pmg your second comment is kind of confusing. Is there a simpler way to interpret that. (Sorry only a beginner ) – comicalvery Jun 29 '20 at 13:30
  • The land of floating-point numbers is full of unexpected surprises. Once you define something to be a `double` (or `long double` or `float`) the usual mathematical rules no longer apply (in corner / edge cases). – pmg Jun 29 '20 at 14:23
  • Why does code print negative `answer` as positive? – chux - Reinstate Monica Jun 29 '20 at 14:53
  • because it times it by -1 ? – comicalvery Jun 30 '20 at 13:17
  • @Eric Postpischil, Ok it wasn't 30 zeros but it was more then was intended. I will edit the question to show the output. – comicalvery Jun 30 '20 at 13:25
  • Lots of people have been saying I make the final answer positive even though it is negative, My reasoning is when the answer increases it shows a negative number which is kind of confusing for a user, so I wrote `The answer has been increased and the final value is: 900.000000 percent` so it was a bit more clear – comicalvery Jun 30 '20 at 13:34
  • @webetreesorg: That actual output makes a huge difference. “30 0's” would mean we are looking for a bug in your source code. “900.000000” is normal output for `%f` and means we are looking for a different formatting method. If you want to program computers well, learn to be exact and pay attention to details. – Eric Postpischil Jun 30 '20 at 20:28
  • @Eric Postpischil, thanks for the feedback, will be sure to have a bit more attention to my code! – comicalvery Jul 01 '20 at 11:57

3 Answers3

7

Is there a way I can detect if the answer is a whole number and only display that number?

To detect if float is a whole number, use modff() to break a float into its whole number and fractional parts.

float f;
float ipart;
float fpart = modff(f, &ipart);
printf("%g is %s whole number.\n", f, fpart == 0.0 ? "a" : "not a");

An alternative to detecting "whole-ness", use "%g" to print floating point numbers with reduced output.

printf("%g\n", 2.0/3.0);  // 0.666667
printf("%g\n", 1234.0);   // 1234

Perhaps a step further with "%g". Use a precision wide enough to show any non-zero digits to the right of the . and let the specifier lop off the trailing zeros when the answer is a whole number.

printf("%.*g\n", FLT_DECIMAL_DIG, some_float);
printf("%.*g\n", DBL_DECIMAL_DIG, some_double);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
5

Compare answer to the return value of f.e. the floorf() function (header math.h) - floorf() since you dealing with a variable of type float - with answer passed as argument.

By doing so, you proof if answer contains an even decimal value.

For the output itself, Use a precision specifier (f.e. .0) which specifies the amount of digits in the fraction part and place it between the % and the f conversion specifier, For example %.0f.

The precision of .0 specifies that you want to display no fraction part.

// Checking if the answer is an increase or decrease

if ( answer > 0 ) {

      if ( answer == floorf(answer) )     // If answer contains a decimal value.
          printf("The answer has been decreased and the final value is: %.0f\n", answer);
      else
          printf("The answer has been decreased and the final value is: %.3f\n", answer);
}
else {

      if ( answer == floorf(answer) )     // If answer contains a decimal value.
          printf("The answer has been increased and the final value is: %.0f\n", answer * -1);
      else 
          printf("The answer has been increased and the final value is: %.3f\n", answer * -1);     
}

Side Notes:

  1. Note that floating-point often does not provide expected results: Is floating point math broken? So, it is possible that even this technique will not work at each and every use case.

  2. Always check the return value of input functions such as scanf() if an input error occurred.

  3. I used floorf(), but ceilf(), truncf() or roundf() could also be used to achieve the same effect.

  4. int main() is deprecated. Use int main(void) instead which declares a full prototype for main().

  5. Since answer will be negative when reaching the else body, printing answer * -1 will output a positive value, since - * - = +. Maybe this is not intended, so this just as a hint.

  • Does this work correctly for integers not exactly representable as a float? I don't think so, but FP math is tricky. If it doesn't, would `modff` work correctly? (also not sure about that one). – Voo Jun 30 '20 at 13:37
  • @Voo The problem has nothing to do about using `floorf()` or friends as suggested in my answer to answer the question given by OP. The problem is the float arithmetic in OP's example *before* any detection at all takes place. The comparison to the return value of `floorf()` is absolutely appropriate for what OP want to do. That it is susceptible is not my fault. The method by using `modff()` as suggested in chux's answer falls too if the arithmetic isn't well. It is a generic problem. Maybe the use of integer types would be better. – RobertS supports Monica Cellio Jun 30 '20 at 13:37
  • @Voo "*If it doesn't, would `modff` work correctly? (also not sure about that one).*" - No. As you can see, chux uses more or less the same algorithm with `fpart == 0.0` - He compares the fraction part to infinite 0. This will also not work if the fraction part isn't infinite 0 by an supposed fully even integer value due to the flawed floating arithmetic. – RobertS supports Monica Cellio Jun 30 '20 at 13:56
  • Yeah my error was worrying about the case of a float abc.xyz that is representable but abc would not be. While that could happen it wouldn't change the result. – Voo Jun 30 '20 at 16:49
-1

My way of checking involves :

if(num1 == (int)num1) // This checks whether num1 is integer
{
     //Do something
}
else
{
     //num1 is float
}
Arshad
  • 11
  • 2
  • Yeah, I tried that, but how do I display only the integer itself? – comicalvery Jun 29 '20 at 07:02
  • Just use `printf("%d",(int) num1);` Or you can use format specifier like `printf("%.0f",num1);` That number after **.** in format specifier is used to display number of decimal places using 0 will print 0 decimal digits – Arshad Jun 29 '20 at 07:08
  • 2
    Try your test with the float number `2147483648`. – bitmask Jun 29 '20 at 07:11
  • Lol , Just in case check with `num1 == (long long) num1` – Arshad Jun 29 '20 at 07:15
  • 4
    Have a go at `18446744073709551616` then. Yes, that is a representable `float`. The point is, don't cook your own functions for things that already have well-tested library support. In this case, have a look at `roundf`. – bitmask Jun 29 '20 at 07:23
  • How would you check if its an integer using `roundf` – Arshad Jun 29 '20 at 07:37
  • See [RobertS's answer](https://stackoverflow.com/a/62633318/430766). – bitmask Jun 29 '20 at 07:43
  • 1
    This is simple test that works for those floats that represent an int exactly. The question is unclear enough that this is a reasonable answer to one possible interpretation of the question. – President James K. Polk Jun 29 '20 at 13:16