问题 如何打印一个小于另一个double值的double值?


其实我正在用c ++编写范围表达式。所以我想要的是如果我有任何表达式

x<1

然后我的

double getMax(...);

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

我试过这样做

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

但我仍然得到与回报声明相同的价值。

我认为C ++在cout语句中将它转换为最接近的double。

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

输出:

3.200000e+001

9117
2018-02-26 07:09


起源

以下所说的, getMax 没有意义的开放间隔和 getSup 应该准确地返回1。 - Jan Hudec


答案:


首先,您需要确保实际打印足够多的数字以确保所有可表示的值 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并不一定适用于此。在这种情况下计算正确的eps是很困难的。

但是,如果您可以使用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);

返回from的方向的下一个可表示的值。所以我指定了 std::numeric_limits<double>::lowest() 在我的电话中,以确保您获得下一个可表示的价值 少于 这个论点。

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


10
2018-02-26 07:28



评论专线不应该简单 a - a * ...::epsilon()? - Jan Hudec
哦,好吧,它将向零舍入。和 2 * a * ...::epsilon() 如果四舍五入将是正确的值,但如果没有则将两倍大。哎哟哎哟。 - Jan Hudec
@JanHudec 10 在提交代码之前我运行的测试是剩下的。我删除了它。是否乘以 a 是对的,我不知道。选择正确的因素是我所不知道的 - 我的主要观点是使用 nextafter 在C ++ 11中。为了正确计算epsilon,其他人可能会做出答案。 - jogojapan
另一件事是我怀疑ε对于之前可表示的值不能正常工作。因为在1之前,下一个值是1.fffffffffffffp-1并且是1-2 <sup> 53 </ sup>,但是ε是2 <sup> -52 </ sup>。 - Jan Hudec
+1 /值得注意的是,某些系统在提供的C库中提供此功能,因此即使不使用C ++ 11,您也可以使用它(非移植):例如: kernel.org/doc/man-pages/online/pages/man3/nextafter.3.html (标准:C99,POSIX.1-2001) - Tony Delroy


我认为你有正确的想法。 查看 不使用流设置double的精度(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


0
2018-02-26 07:28