11

实际上,我正在研究 C++ 中的范围表达式。所以我想要的是如果我有任何表达

x<1

然后我的

double getMax(...);

应该在数轴上返回一个刚好在 1.000(双精度)之前的双精度值。

我试着这样做

double getMax(double& a)
{
    return (a-numeric_limits<double>::min());
}

但我仍然得到与返回语句相同的值。

我认为 C++ 正在将其转换为 cout 语句中最接近的双精度。

int main()
{
    double a = 32;
    cout<<scientific<<getMax(a)<<endl;
    return 0;
}

输出:

3.200000e+001
4

2 回答 2

10

首先,您需要确保实际打印足够多的数字以确保double显示所有可表示的值。您可以按以下方式执行此操作(确保您#include <iomanip>这样做):

    std::cout << std::scientific << std::setprecision(std::numeric_limits<double>::max_digits10) << getMax(a) << std::endl;

其次,numeric_limits<>::min不适合这个。如果您的起始值为1.0,则可以使用numeric_limits<double>::epsilon,这是可表示的最小差异1.0

但是,在您的代码示例中,起始值为32. Epsilon 不一定适用于此。在这种情况下计算正确的 epsilon 是很困难的。

但是,如果您可以使用 C++11 (*),则标头中有一个函数cmath可以满足您的需要std::nextafter

#include <iostream>
#include <limits>
#include <iomanip>
#include <cmath>

double getMax(double a)
{
  return std::nextafter(a,std::numeric_limits<double>::lowest());
}

int main()
{
    double a = 32;
    std::cout << std::scientific
              << std::setprecision(std::numeric_limits<double>::max_digits10)
              << getMax(a)
              << std::endl;
    return 0;
}

我也把它放在liveworkspace上。

解释:

double nextafter(double from, double to);

在 to 的方向上返回 from 的下一个可表示值。因此,我std::numeric_limits<double>::lowest()在调用中指定以确保您获得的下一个可表示值小于参数。

(*)请参阅下面的 Tony D 评论。您可以在nextafter()没有 C++11 的情况下访问。

于 2013-02-26T07:28:31.843 回答
0

我认为你的想法是正确的。查看在不使用流 (ios_base::precision) 的情况下设置双精度不是这个问题,而是他们给出的使用示例precision。您可能想尝试以 53 的精度打印。

我通常看到“接近但不完全”的方式涉及设置差异阈值(通常称为 epsilon)。在这种情况下,您不会使用getMax函数,而是使用小于的 epsilon。(你可以用 epsilon 值和运算符重载来做一个类。我倾向于避免像瘟疫一样的运算符重载。)

基本上,你需要:

bool lessThanEpsilon(double number, double lessThan, double epsilon)
{
    return (lessThan - number >= epsilon);
}

当然,还有其他品种。等于会检查if Math.abs(number - equals) < epsilon

于 2013-02-26T07:28:27.537 回答