与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;
}
答案 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.