比较double和int,不进行强制转换或转换

roy*_*g86 1 c++ precision expression

在我们拥有的一个C++模块中,我们有一个表达式评估语言.

                                \
EVDataElement NAME::eval(   const EvalContext &ec,                          \
                        const bool recursiveFlag,                       \
                        EVEvaluatorTraceFormatter * trace )             \
{                                                                           \
/*  EVTimer timer("(DECLARE_REL_EVAL)","eval","*", "", 1,1, 3);      */     \
    EVDataElement val (                                                     \
        (left->eval(ec, recursiveFlag, trace))                              \
        OP (right->eval(ec, recursiveFlag, trace)) );                       \
    return val;                                                             \
}

DECLARE_REL_EVAL(oLT,<)
DECLARE_REL_EVAL(oLE,<=)
DECLARE_REL_EVAL(oGT,>)
DECLARE_REL_EVAL(oGE,>=)
DECLARE_REL_EVAL(oEQ,==)
DECLARE_REL_EVAL(oNE,!=)
Run Code Online (Sandbox Code Playgroud)

该模块允许设置某些配置规则.

所以,如果数据库中有一条规则表示field1-field2> param1,它会通过传递给上面的表达式语言并返回结果来验证这种情况.

我们现在面临的问题是param1 = 3,field1 = 6.15,field2 = 3.15

它说结果是真的.而且我认为这是因为6.15和3.15的差异导致3.00

当3.00与3比较时,它认为3.00更大.有什么方法可以解决这个问题吗?

我说我们不能使用强制转换的原因是因为我们永远不知道左右可能会出现什么数据类型.我希望这个问题有道理.

Max*_*ert 5

在处理不同基元类型的值时,您将获得"通常的转换".我认为没有办法解决这个问题.

如果你要将ints与doubles 进行比较,那么在确定两个值是否"足够接近"时,你需要提出你想要使用的规则.您可以考虑使用std::modf函数(in <cmath>)进行比较.

考虑:

#include <iostream>
#include <cmath>

int main()
{
    double d = 6.15 - 3.15;
    std::cout << std::boolalpha;
    std::cout << "d == 3.0: " << (d == 3.0) << '\n';
    double i;
    d = std::modf(d, &i);
    std::cout << "i = " << i << ", d = " << d << '\n';
    std::cout << "i == 3.0: " << (i == 3.0) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

在默认设置上使用Visual Studio 2010(即,使用fastmath),我得到:

d == 3.0: false
i = 3, d = 4.44089e-016
i == 3.0: true
Run Code Online (Sandbox Code Playgroud)

3.0可能在二进制浮点数学中完全可表示,但6.15 - 3.15不在3.0二进制浮点数学中.


已经有两篇参考文献" 每个计算机科学家应该知道什么关于浮点运算 ",它描述了二进制浮点数学如何工作,以及它如何不总是符合人类的期望.要记住的要点是,你几乎不想比较两个浮点数的相等性,特别是如果这些数中的一个(或两个)是数学运算的结果.

但是,在你的情况下,你试图将a double与a进行比较int,我必须假设你想要一些舍入.你可能想要考虑3.1相当于3.你可能不会.我真的不知道.

如果你要使用小学教授的舍入约定(在.5或更高版本上),你可以做以下事情:

#include <iostream>
#include <cmath>

int main()
{
    double d = 6.15 - 3.15;
    std::cout << std::boolalpha;
    std::cout << "d == 3.0: " << (d == 3.0) << '\n';
    // note:  this rounds negative numbers the wrong direction
    std::cout << "d is 'close enough' to 3.0: " << (std::floor(d + 0.5) == 3.0) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

还有更复杂的可能性,包括论文中描述的可能性.

  • @rorymustang:您可能没有意识到浮点数在显示时通常是四舍五入的(这与"计算机中的浮点数学计算方法与手工操作的计算方法不同"是一个单独的问题).`std :: cout ,, 1.23456789`可能会显示类似`1.23457`的内容. (2认同)