Joh*_*erg 3 c++ floating-point
考虑
auto x = a + (b-a)*v;
Run Code Online (Sandbox Code Playgroud)
其目的是要建立在范围内的值[a,b)由系数v中[0,1.0).从纯数学的角度来看x>=a,和x<b.但是,我们如何证明或确保这适用于浮点?
a,b,v是同一类型的非负的有限浮点值(double或float)和b>a(最初称b>=a这是与我的要求明显不符x),和v<=netxtafter(1.0,0)(也就是说,它只是低于1.0).
这似乎是显而易见的,b-a >0因此(b-a)*v >=0我们不需要检查:
if (x<a) return a;
Run Code Online (Sandbox Code Playgroud)
但这也是多余的吗?
if (x>=b) return std::nextafter(b,a);
Run Code Online (Sandbox Code Playgroud)
可能编译器(优化)重写表达式来影响这些问题吗?浮点表示的类型是否输入?(我最感兴趣的是最常见的(iec559/IEEE 754).
很明显,ba> 0,因此(ba)*v> = 0,所以我们不需要检查:
if (x<a) return a;
该属性b - a > 0在IEEE 754中是正确的,但我不会说它是显而易见的.在浮点标准化的时候,Kahan 争夺这个属性,因为"逐渐下溢"是真的.其他提案没有低于正常的数字,也没有成功.你可以拥有b > a和b - a == 0在这些其他提案中,例如通过获取a最小的正数b及其后继数.
即使没有逐渐下溢,在一个错误实现IEEE 754的系统上,通过将次正规值刷新为零,也b > a意味着b - a >= 0,因此无需担心x低于此值a.
但这也是多余的吗?
if (x>=b) return std::nextafter(b,a);
即使在IEEE 754中,这个测试也不是多余的.例如b,它是继承者a.对于v上面的所有值0.5,在默认的舍入到最近模式中,结果a + (b-a)*v是b,您试图避免.
我的示例是使用不寻常的值构建的a,b因为这样可以使我免于编写程序以通过暴力查找反例,但不要假设其他更可能的值对a并且b不会出现问题.如果我正在寻找其他反例,我会特别寻找浮点减法b - a向上舍入的值对.
编辑:哦,好吧,这是另一个反例:
就拿a是的继任者的继任者-1.0(即,在双精度,采用C99的十六进制表示,-0x1.ffffffffffffep-1)和b要3.0.然后b - a向上舍入到4.0,并且v成为前者1.0,a + (b - a) * v 最后到达3.0.
浮点减法b - a围捕不需要的一些值a,并b制作一个反例,如在这里:以a作为继任者1.0,并b为2.0也适用.
| 归档时间: |
|
| 查看次数: |
130 次 |
| 最近记录: |