我正在尝试使用差商找到贝塞尔曲线的斜率。差商为:
( f(x + h) - f(x) ) / h
在微积分中,我们通常使用极限,假设 h 无限小并评估公式。在这里,我想做类似的事情,使 h 等于 FLT_MIN 或 FLT_TRUE_MIN,这应该是最小的正浮点值。然而,当我运行 getApproxNormal(0.5f) 时,我只是得到 0,而不是正常值的大致范围。
// _p0 = (0,0)
// _p1 = (0,100)
// _p2 = (100,100)
typedef sf::vector2f Vec2f;
getBezierPoint(float t)
{
float x = powf(1 - t, 2) * _p0.x + 2 * (1 - t) * t * _p1.x + std::pow(t, 2) * _p2.x;
float y = powf(1 - t, 2) * _p0.y + 2 * (1 - t) * t * _p1.y + std::pow(t, 2) * _p2.y;
return Vec2f(x, y);
}
getApproxNormal(float t)
{
Vec2f d = (getBezierPoint(t + FLT_MIN) //both calls return the same value
- getBezierPoint(t)) / FLT_MIN;
return -(d.x / d.y); // returns the negative inverse of the derivative
}
知道是什么原因造成的吗?
我尝试将 FLT_MIN 替换为 0.000001f,这在大概范围内,但为什么 FLT_MIN 仍然是 0?
即使计算参数
t + FLT_MIN
,也会得到相同的结果。此加法的结果将是 t
。这就是浮点数的工作原理。 FLT_MIN
是计算结果可以获得的最小值,但这并不意味着如果将其添加到0
,那么您将得到0
以外的数字。浮点数允许您使用非常小的值和非常大的值,但不能同时使用小值和大值。增量步长取决于值的指数。
这是一个简单的示例(不考虑尾数溢出):
float t = 1;
auto i = *(uint32_t*)&t;
i++; // mantissa increment
float next_t = *(float*)&i;
std::cout << next_t << " - " << t << " = " << next_t - t;
输出:
1 - 1 = 1.19209e-07
也就是说,最接近的大于 1 的数字与其相差 1.19209e-07。