- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
考虑
auto x = a + (b-a)*v;
这意味着在 [a,b)
范围内创建一个值因数v
在 [0,1.0)
.从纯数学的角度来看,x>=a
, 和 x<b
.但是我们如何证明或确保这适用于 float 呢? 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;
但这也是多余的吗?
if (x>=b) return std::nextafter(b,a);
编译器(优化)可以重写表达式来影响这些问题吗?浮点表示的类型是否进入? (我最感兴趣的是最常见的 (iec559/IEEE 754)。
最佳答案
It seems obvious, that b-a >0, and therefore (b-a)*v >=0, so that we don't need to check:
if (x<a) return a;
属性(property)b - a > 0
在 IEEE 754 中是正确的,但我不会说这很明显。在浮点标准化的时候,Kahan fought for this property resulting from “gradual underflow” to be true .其他提案没有次正规数,也没有使它成为现实。你可以有 b > a
和 b - a == 0
在这些其他提案中,例如采用 a
最小的正数和b
它的继任者。
即使没有逐渐下溢,在通过将次正规数刷新为零来错误实现 IEEE 754 的系统上,b > a
暗示b - a >= 0
, 这样就不用担心 x
低于a
.
But is this also redundant?
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
的继任者的继任者(即,在 double 中,使用 C99 的十六进制表示法 -0x1.ffffffffffffep-1
)和 b
成为3.0
.然后 b - a
四舍五入到 4.0,取 v
成为1.0
的前身, a + (b - a) * v
rounds up至 3.0
.
浮点减法b - a
a
的某些值不需要四舍五入和 b
做一个反例,如图here :服用a
作为1.0
的继任者和 b
作为2.0
也有效。
关于c++ - 准确地创建范围 [a,b) 中的浮点值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42411053/
我是一名优秀的程序员,十分优秀!