给定归一化的浮点数f,f 之后/之前的下一个归一化浮点数是多少.
随着比特twiddling,提取尾数和指数我有:
next_normalized(double&){
if mantissa is not all ones
maximally denormalize while maintaining equality
add 1 to mantissa
normalize
else
check overflow
set mantissa to 1
add (mantissa size in bits) to exponent.
endif
}
Run Code Online (Sandbox Code Playgroud)
但是,这可以通过浮点运算来完成吗?
如
std::numeric_limits<double>::epsilon()
Run Code Online (Sandbox Code Playgroud)
只是1的"邻域"中的误差差异 - 例如:
normalized(d+=std::numeric_limits<double>::epsilon()) = d for d large
Run Code Online (Sandbox Code Playgroud)
它看起来更像错误率而不是错误差异,因此我天真的直觉就是
(1.+std::numeric_limits<double>::epsilon())*f //should be the next.
Run Code Online (Sandbox Code Playgroud)
和
(1.-std::numeric_limits<double>::epsilon())*f //should be the previous.
Run Code Online (Sandbox Code Playgroud)
特别是我有3个问题,任何人都做了以下任何一个(对于IEEE754):
1)对这个问题做了错误分析?
2)证明(或可证明)对于任何标准化的双d
(1.+std::numeric_limits<double>::epsilon())*d != d ?
Run Code Online (Sandbox Code Playgroud)
3)证明对于任何标准化的双数d,不存在双f
d < f < (1.+std::numeric_limits<double>::epsilon())*d ?
Run Code Online (Sandbox Code Playgroud)
正如Robert Kern所说,你需要C nextafter()函数,或IEEE754 nextUp()和nextDown()函数,尽管这两个函数尚未广泛实现.
如果由于某种原因想要避免使用nextafter,你可以这样做:
double next = x + scalbn(1.0, ilogb(x) - 52);
Run Code Online (Sandbox Code Playgroud)
这将x ^的指数增加2 ^(指数x - 52),这恰好是最后一位(ULP)中的一个单位.
如果您没有常用的cmath函数:
double x = 1.0;
uint64_t rep;
assert(sizeof x == sizeof rep);
memcpy(&rep, &x, sizeof x);
rep += 1;
memcpy(&x, &rep, sizeof x);
Run Code Online (Sandbox Code Playgroud)
这通过对浮点值的按位表示进行操作,在x的有效数上加1; 如果下一个值在下一个binade中,这将进入指数,返回正确的值.如果你想让它适用于负值,你需要调整它.
| 归档时间: |
|
| 查看次数: |
2022 次 |
| 最近记录: |