用整数计算浮点数的标准化方法是怎样的?
How is the standarized way to calculate float with integers?
你们知道这在 C 中是如何计算的吗?
uint8_t samplerate = 200;
uint8_t Result;
Result = 0.5 * samplerate;
现在,问题是 0.5 是浮点数而 samplerate
是整数。
Result
可以是 0,因为 0.5 被转换为整数,因此四舍五入为 0 (Result = 0 * 200 = 0
)。或者 Result
可能是 100,因为编译器首先看到 0.5 并将 samplerate
转换为 float (Result = 0.5 * 200 = 100
).
是否有编译器处理这些计算的标准化方式?
我的意思是编译器会首先查看最左边的变量(在本例中为 0.5)并将另一个变量转换为这个,还是会查看最右边的变量(samplerate
)并转换其他变量到这个?
我知道如何解决这个问题,但我正在寻找一个通用的答案,如果这是 C 标准化的,它将如何计算此类方程式?
是的,当然这是由标准控制的,这里没有不确定性。
基本上整数将被提升为 double
(因为 0.5
的类型是 double
,而不是 float
)并且计算将在那里进行,然后结果将被截断回 uint8_t
。通常,编译器会因为精度损失而对您大喊大叫。如果没有,请根据需要添加更多警告选项。
是的,有一个标准。在这种情况下,表达式中的数字会自动转换为更宽的类型(占用更多字节的类型),因此您的表达式将按如下方式计算:
(0.5: double) * (0: uint8_t) => (0.5: double) * (0.0: double) == (0.0: double)
uint8_t Result = (0.0: double) => (0: uint8_t) // this is a forced cast, because Result is of type uint8_t
double
比 uint8_t
宽,所以 (0: uint8_t)
加宽了 到 (0.0: double)
。此转换不会丢失信息,因为 double
占用足够 space 来容纳存储在 uint8_t
.
中的所有数据
当各种类型的数值组合在一个表达式中时,它们受制于通常的算术转换,这是一组规定应转换哪个操作数的规则,什么类型。
这些转换在 C 标准的第 6.3.1.8 节中有详细说明:
Many operators that expect operands of arithmetic type cause
conversions and yield result types in a similar way. The purpose is
to determine a common real type for the operands and result. For the
specified operands, each operand is converted, without change of type
domain, to a type whose corresponding real type is the
common real type. Unless explicitly stated otherwise, the
common real type is also the corresponding real type of the
result, whose type domain is the type domain of the operands
if they are the same, and complex otherwise. This pattern is
called the usual arithmetic conversions :
- First, if the corresponding real type of either operand is long double , the other operand is converted, without change of type domain, to a type whose corresponding real type is long
double .
- Otherwise, if the corresponding real type of either operand is double , the other operand is converted, without change of type domain, to a type whose corresponding real type is
double .
- Otherwise, if the corresponding real type of either operand is float , the other operand is converted, without change of type domain, to a type whose corresponding real type is
float .
- Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted
operands:
- If both operands have the same type, then no further
conversion is needed.
- Otherwise, if both operands have signed
integer types or both have unsigned integer types, the operand
with the type of lesser integer conversion rank is converted
to the type of the operand with greater rank.
- Otherwise, if the
operand that has unsigned integer type has rank greater or
equal to the rank of the type of the other operand, then
the operand with signed integer type is converted to the type
of the operand with unsigned integer type.
- Otherwise, if the
type of the operand with signed integer type can represent all of the
values of the type of the operand with unsigned integer type, then the
operand with unsigned integer type is converted to the type
of the operand with signed integer type.
- Otherwise, both operands are converted to the unsigned integer type
corresponding to the type of the operand with signed integer type.
请特别注意粗体段落,这适用于您的情况。
浮点常量0.5
的类型为double
,所以其他操作数的值被转换为类型double
,乘法运算符的结果*
类型为 double
。然后将此结果赋值回 uint8_t
类型的变量,因此 double
值将转换为此类型进行赋值。
所以在这种情况下 Result
的值为 100。
你们知道这在 C 中是如何计算的吗?
uint8_t samplerate = 200;
uint8_t Result;
Result = 0.5 * samplerate;
现在,问题是 0.5 是浮点数而 samplerate
是整数。
Result
可以是 0,因为 0.5 被转换为整数,因此四舍五入为 0 (Result = 0 * 200 = 0
)。或者 Result
可能是 100,因为编译器首先看到 0.5 并将 samplerate
转换为 float (Result = 0.5 * 200 = 100
).
是否有编译器处理这些计算的标准化方式?
我的意思是编译器会首先查看最左边的变量(在本例中为 0.5)并将另一个变量转换为这个,还是会查看最右边的变量(samplerate
)并转换其他变量到这个?
我知道如何解决这个问题,但我正在寻找一个通用的答案,如果这是 C 标准化的,它将如何计算此类方程式?
是的,当然这是由标准控制的,这里没有不确定性。
基本上整数将被提升为 double
(因为 0.5
的类型是 double
,而不是 float
)并且计算将在那里进行,然后结果将被截断回 uint8_t
。通常,编译器会因为精度损失而对您大喊大叫。如果没有,请根据需要添加更多警告选项。
是的,有一个标准。在这种情况下,表达式中的数字会自动转换为更宽的类型(占用更多字节的类型),因此您的表达式将按如下方式计算:
(0.5: double) * (0: uint8_t) => (0.5: double) * (0.0: double) == (0.0: double)
uint8_t Result = (0.0: double) => (0: uint8_t) // this is a forced cast, because Result is of type uint8_t
double
比 uint8_t
宽,所以 (0: uint8_t)
加宽了 到 (0.0: double)
。此转换不会丢失信息,因为 double
占用足够 space 来容纳存储在 uint8_t
.
当各种类型的数值组合在一个表达式中时,它们受制于通常的算术转换,这是一组规定应转换哪个操作数的规则,什么类型。
这些转换在 C 标准的第 6.3.1.8 节中有详细说明:
Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. The purpose is to determine a common real type for the operands and result. For the specified operands, each operand is converted, without change of type domain, to a type whose corresponding real type is the common real type. Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result, whose type domain is the type domain of the operands if they are the same, and complex otherwise. This pattern is called the usual arithmetic conversions :
- First, if the corresponding real type of either operand is long double , the other operand is converted, without change of type domain, to a type whose corresponding real type is long double .
- Otherwise, if the corresponding real type of either operand is double , the other operand is converted, without change of type domain, to a type whose corresponding real type is double .
- Otherwise, if the corresponding real type of either operand is float , the other operand is converted, without change of type domain, to a type whose corresponding real type is float .
- Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:
- If both operands have the same type, then no further conversion is needed.
- Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
- Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.
- Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.
- Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.
请特别注意粗体段落,这适用于您的情况。
浮点常量0.5
的类型为double
,所以其他操作数的值被转换为类型double
,乘法运算符的结果*
类型为 double
。然后将此结果赋值回 uint8_t
类型的变量,因此 double
值将转换为此类型进行赋值。
所以在这种情况下 Result
的值为 100。