在C语言中对宏值进行的数学操作

huangapple go评论46阅读模式
英文:

Mathematical operation on macro value in C

问题

以下是程序的输出:

原程序输出为:T = 0.0000

修改后的程序输出为:T = 0.000125

请注意,将Fs宏定义更改为浮点变量后,输出值变为0.000125,这是因为在原始程序中,1/Fs 中的Fs是整数,所以结果会被截断为0。但是在修改后的程序中,Fs被声明为浮点数,所以除法操作得到了正确的结果。

英文:

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;
}

答案1

得分: 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);
英文:

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);

答案2

得分: 1

以下是翻译的内容:

能否有人解释正在发生什么?

在 C 中,运算符使用的类型是基于该运算符的操作数选择的,而不是基于存储结果的类型。

此外,包括常量在内,一切都有类型。8000 的类型是 int8000.0 的类型是 double,而 8000.0f 的类型是 float

在使用 Fs 宏表示整数 8000 的情况下,1/Fs,那么除法的两个操作数都是 int 类型。因此,除法是在 int 类型上执行的,结果是 0

如果使用 Fs 类型为 float 来表示 1/Fs,则除法的一个操作数是 int,另一个操作数是 float。有一种被称为 "通常的算术转换"(参见 https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules)的机制,会将 int "提升" 为 float 类型。这时除法是在 float 类型上执行的。


一些最佳实践:

  • 避免将整数/int 常量与浮点运算混合使用。相反,使用纯浮点常量/变量编写涉及浮点的每个表达式。
  • 处理 float 时使用 8000.0f,处理 double 时使用 8000.0
  • float 是 C 程序中几乎不应该使用的类型,在初学者程序中根本不应使用。唯一应该使用 float 的情况是当 CPU 具有单精度 FPU,但不支持 double 精度 - 这是一个非常特定的情况,不适用于现代的 x86 PC,在这些系统中应该在所有地方使用 double
  • 避免编写依赖于隐式类型提升的代码。如果从一开始使用正确的类型,可以避免此类提升。
英文:

> 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 https://stackoverflow.com/questions/46073295/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.

huangapple
  • 本文由 发表于 2023年2月6日 05:57:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75355796.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定