c - 就浮点数而言,它的 msb 是否有正确的常量表达式?
问题描述
问题:给定一个浮点常量表达式,我们能否编写一个宏来计算一个常量表达式,其值是 2 的幂,等于有效数的最高位?等效地,这只是幅度上小于或等于输入的 2 的最大幂。
出于这个问题的目的,我们可以忽略:
- 接近溢出或接近下溢的值(它们可以通过有限的
?:
重新缩放应用程序处理)。 - 负输入(它们可以同样处理)。
- Non-Annex-F-conforming 实现(不能真正用它们做任何有用的浮点运算)。
- 超出精度的怪异(
float_t
并且double_t
可以FLT_EVAL_METHOD
与其他float.h
宏一起使用以安全地处理它)。
因此,对于远离无穷大和非正规范围的正值,它足以解决问题。
请注意,此问题等效于查找特定值的“epsilon”,即nextafter(x,INF)-x
(或 or 中的等价物float
)long double
,结果仅按比例缩放DBL_EPSILON
(或类型的等价物)。如果解决方案更简单,则完全可以接受。
我有一个建议的解决方案,我将其作为自我回答发布,但我不确定它是否正确。
解决方案
如果您可以假设 IEEE 754 binary64 格式和语义(特别是算术运算是正确舍入的),以及舍入到偶数舍入模式,那么对于任何不太小的不太-large 正有限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
。
推荐阅读
- php - asset() 返回 //url... 而不是 http://url
- python - Pycups - 使用 IPPAttribute 创建和发送 IPPRequest 并解析响应(启用 IPP:Hold-New-Jobs)
- unity3d - 当浮点数在统一 2019.4.1f1 中返回 0 时混合树出现问题
- java - 如何在像古吉拉特语这样的java中打印印度地区语言?
- c# - 有什么方法可以基于 GetInstance() 动态转换类型
- c++ - SFML 无法加载图像
- javascript - 如何检查 Typescript AST 节点是否是 javascript 本机函数?
- reactjs - 如何从 Firestore 渲染数据以响应本机组件?
- jquery - 如何使用 jQuery 选择嵌套在数据属性中的 id?
- reactjs - 从父组件的函数体内更新子组件