2016-08-17 8 views
0

私は、ユーザーからの文字列を取り込んで解析する数学計算機を作成しました。これは計算時にすべての値を保持するために倍精度を使用します。一度に解決、私はそれを印刷して、必ずそれが(例えば0.9999999のためにプリントアウト上1なり、正しく出力させるためにstd::setprecision()を使用倍精度/浮動小数点誤差の補償

出力される文字列を返す:。

//return true or false if this is in the returnstring. 

if (returnString.compare("True") == 0 || returnString.compare("False") == 0) return returnString; 

    //create stringstream and put the answer into the returnString. 
    std::stringstream stream; 
    returnString = std::to_string(temp_answer.answer); 

    //write into the stream with precision set correctly. 
    stream << std::fixed << std::setprecision(5) << temp_answer.answer; 


    return stream.str(); 

私は倍精度浮動小数点数を使用するときの精度の問題を認識しています。今日は、ユーザーが2つの数学的な文字列を比較できるようにコードの作業を開始しました。比較演算子の各側の数式表現パーサを使用して、回答を比較します。

私が今直面している問題は、ユーザが1/3*3=1のようなものを入力したときです。もちろん、私は2倍を使用しているので、パーサは答えとして0.999999を返します。通常、非比較の問題を解決するときには、前述のように、これは印刷時にstd::setprecision()で補正されます。しかし、2つの倍を比較すると、それは0.99999!=1として偽に戻ります。この不正確さが補償されている倍数を比較すると、どのようにしてそれを得ることができ、答えは正しく返されますか?ここでは数値を比較するために使用するコードを示します。

bool math_comparisons::equal_to(std::string lhs, std::string rhs) 
{ 
    auto lhs_ret = std::async(process_question, lhs); 
    auto rhs_ret = std::async(process_question, rhs); 
    bool ReturnVal = false; 

    if (lhs_ret.get().answer == rhs_ret.get().answer) 
    { 
     ReturnVal = true; 
    } 

    return ReturnVal; 
} 

何らかの丸めが必要だと思っていますが、それを正しく達成する方法は100%わかりません。これがすでに解決されていれば私を許してください - 私は検索であまり見つけられませんでした。ありがとう!

+0

あなたは 'double'が不正確であるので、どのように' double'使用停止について知っていますか? – MikeCAT

+1

ユーザが整数だけを入力できる場合は、浮動小数点の代わりに小数点以下を使用して作業します(自分で書いてください)。 – molbdnilo

+0

ユーザが '1-.00001'を入力するとどうなりますか?それはまた1と等しいでしょうか? –

答えて

2

answerdoubleであると仮定すると、TOLが適切な許容値である

abs(lhs_ret.get().answer - rhs_ret.get().answer) < TOL 

でこれ

lhs_ret.get().answer == rhs_ret.get().answer 

を置き換えます。

浮動小数点数は==と決して比較しないでください。ただし、絶対差が所定の許容値より小さいかどうかを確認してください。

言及する必要がある難点が1つあります。ダブルスの精度は約16小数です。したがって、TOL=1.0e-16と設定することがあります。数字が1未満の場合にのみ機能します。数字が16桁の場合は、許容差が1でなければなりません。

したがって、数字が10e8より小さく、 10e-8のような比較的大きな許容差があるか、もっと複雑なことをする必要があります。

+0

ありがとう、これは私が実装したソリューションであり、素晴らしいです!ちょっと時間を費やして、許容値を微調整するだけです。 – Swemoph

1

まず考えてみます。

親指の基本的なルールとして、doubleがdpは小数点以下の桁、または1.0e-16でおよそ16dpとの値になります。これは、これがIEの10分の1未満の数字にのみ適用されることに注意する必要があります。その事実の周りで操作する必要があるのは、15 dp EGしかありません。10.0e-15など...コンピュータベース2で数え、ベース10で数える人は、"most"近代的なOSのビット範囲では決して適切に表現できません。

これは、2進数または2進数で0.1を表すことが無限に長いという事実によって強調されます。

したがって、==演算子で有理数を比較しないでください。代わりに、従来通りに使用される「行き先」ソリューションは、

「十分に近い」ソリューションを実装します。 IE:値としてを定義し、(value a - value b) < epsilon == trueの場合はそれを指定します。我々の言いたいことは、私たちのプログラムのすべての目的と目的のために、それが真実とみなされるのに十分近いことです。if a - b is within eです。

ここで、イプシロンの値を選択するには、目的がどれだけ正確である必要があるかによって異なります。たとえば、2Dサイドスクロールプラットフォームのゲームと比較して、構造エンジニアリングに高いレベルの正確さが必要と想定することができます。

あなたはあなたのコードの行7交換することがあなたのケースでのソリューション:ABSは絶対値である

abs(lhs_ret.get().answer - rhs_ret.get().answer) < epsilon

(lhs_ret.get().answer == rhs_ret.get().answer)

を。 IEの値はlhsの符号を無視しています。

私は、この講義をMITオープンコースウェアで非常にお勧めします。このコースは簡単に解説します。

http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00sc-introduction-to-computer-science-and-programming-spring-2011/unit-1/lecture-7-debugging/

関連する問題