问题:给定一个浮点常量表达式,我们可以编写一个宏来计算一个常量表达式,该常量表达式的值是等于尾数最高位的 2 的幂吗?同样,这只是小于或等于输入幅度的两个的最大幂。
就这个问题而言,我们可以忽略:
- 接近溢出或接近下溢的值(可以通过有限多次应用
?:
来重新缩放)。 - 负输入(可以同样处理)。
- 不符合Annex-F标准的实现(实际上不能用它们做任何有用的浮点运算)。
- 关于精度过高的怪异(
float_t
和double_t
可以与FLT_EVAL_METHOD
和其他float.h
宏一起使用以安全地处理它)。
因此,只要解决远离无穷大和非正规范围的正值问题就足够了。
请注意,此问题相当于查找特定值的“epsilon”,即 nextafter(x,INF)-x
(或 float
中的等效项) > 或 long double
),结果仅按 DBL_EPSILON
(或该类型的等效值)缩放。如果解决方案更简单,则完全可以接受。
我有一个建议的解决方案作为 self 回答发布,但我不确定它是否正确。
最佳答案
如果您可以假设 IEEE 754 二进制 64 格式和语义(特别是算术运算正确舍入)以及舍入到偶数舍入模式,那么这是一个很好的事实对于任何不太小也不太大的正有限double
值x
,从 x
开始的下一个可表示值总是由 x / 0x1.fffffffffffffp-1
给出(其中 0x1.fffffffffffffp-1
只是拼写为十六进制文字的 1.0 - 0.5 * DBL_EPSILON
)。
因此,我们可以简单地从以下位置获得您要求的最高有效位:
(x / 0x1.fffffffffffffp-1 - x) * 0x1.0p+52
当然,float
也有类似的结果。 ,假设 IEEE 754 binary32 格式和语义。
事实上,唯一失败的正常正值是 DBL_MAX
,除法结果溢出到无穷大。
要证明除法技巧有效,只要证明x
就足够了。在 1.0 <= x < 2.0
范围内;很容易证明对于任何 x
在此范围内,x / 0x1.fffffffffffffp-1 - x
的值(其中 /
在本例中表示数学除法)位于半开区间 (2^-53, 2^52]
内,因此在舍入到偶数(或实际上任何舍入到最近的舍入模式)下,x / 0x1.fffffffffffffp-1
四舍五入到下一个可表示的值。
同样,在相同的假设下,x * 0x1.fffffffffffffp-1
始终是从 x
开始的下一个可表示值.
关于c - 就浮点而言,是否有正确的常量表达式用于其最高有效位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53598657/