【问题标题】:How to compare double variables in the if statement如何比较if语句中的双变量
【发布时间】:2018-03-21 10:58:26
【问题描述】:

当我试图比较这些双打时,它似乎无法正常工作

这里是:(这正是我的问题)

#include <stdio.h>
#include <math.h>

int main () {
    int i_wagen;
    double dd[20];
    dd[0]=0.;
    dd[1]=0.;
    double abstand= 15.;
    double K_spiel=0.015;
    double s_rel_0= K_spiel;
    int i;

    for(i=1; i<=9; i++)
    {
        i_wagen=2*(i-1)+2;
        dd[i_wagen]=dd[i_wagen-1]-abstand;
        i_wagen=2*(i-1)+3;
        dd[i_wagen]=dd[i_wagen-1]-s_rel_0;
    }
    double s_rel=dd[3-1]-dd[3];

   if((fabs(s_rel) - K_spiel) == 0.)
   {
       printf("yes\n");
   }
   return(0);
}

执行程序后,不会打印yes。

【问题讨论】:

  • 在您发布的代码中没有明显的错误。您需要对此进行调试,或提供minimal reproducible example 以及输入(如果有)、实际和预期输出。
  • 您正在比较 不同 矩阵值。会不会是这个原因?
  • coeffx 中存储的值是什么?
  • 请为您的问题提供MCVE
  • 我敢打赌,当 MCVE 到来时,它将是 stackoverflow.com/questions/588004/… 的副本

标签: c if-statement double comparison


【解决方案1】:

如何比较if语句中的双变量?

考虑浮点数双精度表示的有限精度!

您的问题很简单,在Is floating point math broken? 中有介绍

浮点运算不精确。给定数字的表示可能不精确。

对于标准 binary64 格式的0.1,表示可以完全写成0.1000000000000000055511151231257827021181583404541015625

双精度 (double) 仅提供 52 有效位、11 指数位和 1 符号位。 C 中的浮点数使用 IEEE 754 编码。

查看程序的输出以及可能的解决方法,因为变量接近0.0

#include <stdio.h>
#include <math.h>

#define PRECISION  1e-6

int main (void) {

    int i_wagen;
    double dd[20];

    dd[0]=0.;
    dd[1]=0.;

    double abstand= 15.;
    double K_spiel=0.015;

    double s_rel_0= K_spiel;
    int i;

    for(i=1; i<=9; i++)
    {
        i_wagen = 2*(i-1)+2;

        dd[i_wagen] = dd[i_wagen-1]-abstand;
        i_wagen = 2*(i-1)+3;

        dd[i_wagen] = dd[i_wagen-1] - s_rel_0;
    }

    double s_rel = dd[3-1]-dd[3];

    printf(" s_rel %.16f K_spiel %.16f  diff  %.16f \n" , s_rel, K_spiel, ((fabs(s_rel) - K_spiel)) );

    if((fabs(s_rel) - K_spiel) == 0.0) // THIS WILL NOT WORK!
    {
       printf("yes\n");
    }

    //  Settle down for being close enough to 0.0     
    if( fabs( (fabs(s_rel) - K_spiel)) < PRECISION)
    {      
       printf("yes!!!\n");
    }

    return(0);
}

输出:

s_rel 0.0150000000000006 K_spiel 0.0150000000000000  diff  0.0000000000000006                                      
yes!!!

【讨论】:

  • 这正是我的问题。非常感谢您的时间投入。
  • @MohamedAzzam 谢谢!我很高兴能帮上忙。
【解决方案2】:

您将 x 与两个不同的矩阵条目进行比较:第一个 if 将 x 与 coeff[0][0] 进行比较,仅次于 coeff[0][1]。因此,如果 x 大于 coeff[0][0] 且小于或等于 coeff[0][1] 程序将执行最后的 else 分支。您可能希望将 x 与两个 if 语句中的相同矩阵条目进行比较。在这种情况下,最后一个 else 分支将毫无用处,因为三种情况之一(小于、等于或大于)必须为真。

【讨论】:

  • 不是这样的,我确实想要这样。我想知道的是,如果我比较 double 或 int 会有什么不同吗?我需要处理不同的程序吗?
  • @MohamedAzzam 请编辑您的问题并提供minimal reproducible example!!
【解决方案3】:

首先,声明中使用的dd[i_wagen-1]

dd[i_wagen]=dd[i_wagen-1]-abstand;

未初始化。代码会运行,但会产生不可预知的结果。 要初始化,您可以使用:

double dd[20]={0}; //sufficient

或者可能

double dd[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //explicit, but not necessary

转到您的实际问题,这一切都归结为以下陈述:

if((fabs(s_rel) - K_spiel) == 0.)

您已将 K_spiel 初始化为 0.015。在您的执行流程中,此时s_rel 似乎接近 0.015。但它实际上更接近 0.0150000000000006。所以比较失败。

一个常用的技巧是定义一个 epsilon 值,并使用它来确定两个浮点值之间的差异是否小到足以满足您的目的:

来自 The Art of Computer Programming,以下 sn-p 使用这种方法,并且适用于您非常具体的示例:(注意:Read why this approach will not work for all floating point related comparisons.

bool approximatelyEqual(float a, float b, float epsilon)
{
    return fabs(a - b) <= ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
}

所以换行:

if((fabs(s_rel) - K_spiel) == 0.)

if(approximatelyEqual(s_rel, K_spiel, 1e-8)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    • 2018-02-01
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多