1

The output of the following program is T = 0.0000.

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

#define Fs 8000

int main()
{
    float T = 1/Fs;
    printf("T = %f", T);
    
    return 0;
}

However, when the macro Fs is declared as a float variable inside main, I get the correct output T = 0.000125. Can anyone explain what is going on? Is it possible to get the correct output with the macro too?

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

int main()
{
    float Fs = 8000;
    float T = 1/Fs;
    printf("T = %f", T);
    
    return 0;
}
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
MaxFrost
  • 217
  • 1
  • 6
  • 3
    You are getting the correct answer when you divide by a `float`. You are getting an incorrect answer when you divide by an `int`. See [What is the behavior of integer division?](https://stackoverflow.com/questions/3602827/what-is-the-behavior-of-integer-division) – Drew Dormann Feb 05 '23 at 21:59
  • 1
    An int divided by an int gives you an int. It doesn't matter if the variable on the left side of the `=` is float. The "damage" has already been done on the right side of the `=`. – PaulMcKenzie Feb 05 '23 at 22:00
  • 1
    Do not tag C++ for C questions. – Eric Postpischil Feb 05 '23 at 22:04
  • 2
    OT: You only use `#include ` when using definitions or function prototypes from that library (like `sin()` or `atan()`). It is not needed for basic floating point operations. (PS: Use `double` instead of `float` unless there are other constraints.) – Fe2O3 Feb 05 '23 at 22:06
  • Does this answer your question? [Why does division result in zero instead of a decimal?](https://stackoverflow.com/questions/8906722/why-does-division-result-in-zero-instead-of-a-decimal) – phuclv Feb 06 '23 at 01:17
  • duplicate: [Dividing 1/n always returns 0.0](https://stackoverflow.com/q/13331054/995714) – phuclv Feb 06 '23 at 01:19

2 Answers2

1

Integer divided by integer = integer. Integer divided by float = float. Either:

#define Fs 8000.0

and/or

float T = 1.0/Fs;

and/or

float T = 1/(float)(Fs);
John3136
  • 28,809
  • 4
  • 51
  • 69
  • 3
    Nitpick: `1.0` is a `double`, not a `float`. `1.0f` is clearer. Ditto for `8000.0`. Only mentioning because for more involved code, the compiler might generate a bunch of instructions to convert things from float to double and back again. – pmacfarlane Feb 05 '23 at 22:09
1

Can anyone explain what is going on?

In C the type used by an operator is picked based on that operator's operands and not based on the type where you store the result.

Also everything including constants has a type. 8000 is type int, 8000.0 is type double and 8000.0f is type float.

In case of 1/Fs with Fs as a macro for the integer 8000, then both operands of the division are int. Therefore the division is carried out on int type and you get the result 0 because of it.

In case of 1/Fs with Fs as type float, one operand of the division is int and the other is float. Something called "the usual arithmetic conversions" (see Implicit type promotion rules) then "promotes" the int to type float. The division is carried out on float type.


Some best practices:

  • Avoid mixing integers/int constants with floating point arithmetic. Instead write every expression involving floating point with pure floating point constants/variables.
  • Use 8000.0f when dealing with float and 8000.0 when dealing with double.
  • float is a type that should barely ever be used in C programs and never in beginner programs. The only scenario where you should ever use float is when your CPU has a single precision FPU but no hardware support for double precision - which is a very specific scenario and not applicable to modern x86 PC where double should be used everywhere.
  • Avoid writing code relying on implicit type promotions. If correct types are used from the start, such promotions can be avoided.
Lundin
  • 195,001
  • 40
  • 254
  • 396