英文:
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
的类型是 int
,8000.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 withfloat
and8000.0
when dealing withdouble
. 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 usefloat
is when your CPU has a single precision FPU but no hardware support fordouble
precision - which is a very specific scenario and not applicable to modern x86 PC wheredouble
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论