1

私たちが持っている C++ モジュールの 1 つに、式評価言語があります。

                                \
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,!=)

このモジュールでは、特定の構成ルールを設定できます。

SO、データベースに field1 - field2 > param1 というルールがあった場合、上記の式言語に渡してこの条件を検証し、結果を返します。

現在直面している問題は、param1 = 3、field1 = 6.15、field2 = 3.15 です。

結果は正しいと言っています。そして、6.15 と 3.15 の差が 3.00 になるからだと思います。

そして、3.00 と 3 を比較すると、3.00 の方が大きいと思います。これを回避する方法はありますか?

キャストを使用できないと言った理由は、左右のデータ型がどのようなものになるか分からないからです。この質問が理にかなっているといいのですが。

4

2 に答える 2

5

さまざまなプリミティブ型の値を処理するときに、「通常の変換」を取得します。これを回避する方法はないと思います。

intsとsを比較するdouble場合は、2つの値が「十分に近い」かどうかを判断するときに使用するルールを考え出す必要があります。比較を行う際に、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';
}

デフォルト設定でVisualStudio2010を使用する(つまり、使用しないfastmath)と、次のようになります。

d == 3.0: false
i = 3, d = 4.44089e-016
i == 3.0: true

3.0バイナリ浮動小数点演算では正確に表現できる可能性がありますが、バイナリ浮動小数点演算では表現でき6.15 - 3.15ません3.0


バイナリ浮動小数点演算がどのように機能するか、そしてそれが人間の期待に常に適合するとは限らないことを説明する論文「すべてのコンピュータ科学者が浮動小数点演算について知っておくべきこと」への2つの参照がすでにあります。覚えておくべき主なポイントは、特にこれらの数値の一方(または両方)が数学演算の結果である場合、2つの浮動小数点数が等しいかどうかを比較することはほとんどないということです。

ただし、あなたの場合は、をと比較しようとしてdoubleいるので、丸めが必要であるintと想定する必要があります。と同等であると見なすことができます。あなたはそうではないかもしれません。本当にわかりません。3.13

小学校で教えられている丸め規則(.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';
}

論文で説明されているものを含め、はるかに複雑な可能性があります。

于 2012-05-02T18:26:31.137 に答える
1

field1 - field2 > param1forが必要な場合はparam1 = 3、算術を使用する必要がありますfield1 = 6.15field2 = 3.15infinite precision

上記の浮動小数点演算に関する論文をお読みください。

于 2012-05-02T18:55:44.603 に答える