自动设置更高的精度以在C中浮动

时间:2013-12-09 10:07:57

标签: c numerical-methods floating-point-precision

与typedef t_float相比,我想自动设置更高的delta_prime精度,以避免取消问题,以便用户可以根据需要更改t_float。 也许我可以尝试获得浮点精度,但我不知道如何正确地做到这一点。

在我的typedefs.h:

typedef double t_float;

在某些code.c中:

t_float solve_quadratic(const t_float a, const t_float b_prime, const t_float c)
{
    long double delta_prime = b_prime * b_prime - a * c;

    if (delta_prime < 0.0)
        return INF;

    return (b_prime + sqrt(delta_prime)) / a;
}

2 个答案:

答案 0 :(得分:1)

您可以使用模板构建“类型地图”。 Boost的MPL有一个“地图”,或者您可以自己动手:

template <typename Numeric>
struct precision_enlarger;

template <>
struct precision_enlarger<float> { typedef double type; };

template <>
struct precision_enlarger<double> { typedef long double type; };

template <>
struct precision_enlarger<long double> { typedef long double type; };

然后在你的代码中:

typename precision_enlarger<t_float>::type delta_prime = // ...

答案 1 :(得分:0)

为避免大量精度损失而无法使用更高的精度,可以重新安排计算。

const t_float a, const t_float b_prime, const t_float c

// The concern here is when `a*c` is positive, no cancellation when negative.
//long double delta_prime = b_prime * b_prime - a * c;

t_float ac = a*c;
t_float Discriminant;
t_float Discriminant_sr;
if (ac <= 0.0) {
  Discriminant = b_prime * b_prime - ac;
  // or Discriminant_sq = hypot(b_prime, sqrt(-ac));
}
else {
  ac = sqrt(ac);
  // When result approaches 0.0, half the precision loss v. b_prime * b_prime - a*c
  Discriminant = (b_prime - ac) * (b_prime + ac);
  // Note: Discriminant can only be negative via this path
}

// Assume + and - root are equally valid, so use the one that does not cause cancellation.
// b_prime + sqrt(Discriminant)) / a;
Discriminant_sr = sqrt(Discriminant);
t_float Root1;
if (b_prime >= 0.0) {
  Root1 = (b_prime + Discriminant_sr) / a;
else
  Root1 = (b_prime - Discriminant_sr) / a;
return Root1;

// If the other root is needed, it likely may be calculated from _something_ like 
Root2 = c/Root1.