2016-10-12 11 views
-1

Cの浮動小数点数があまり正確ではないことに気付いています。しかし、なぜ私はそのような結果を得ているのか理解できない洞察を持っています。 まず、1行で計算を行うと、結果として「0」が間違っています。 同じ計算をいくつかのコマンドに分割して、私が期待していたものをほぼ得ています。C数学ライブラリ - 浮動小数点計算?

だから、最初の質問:

  1. なぜ一行は、分割線が異なるのですか?
  2. もっと正確に計算する方法はありますか? 320-(10.44 * 4)は278.24で、278.23999でなくてはなりません!私は根やpiなどの数で丸め問題を理解しています。しかし、上記の例ではありません。

[OK]を、ここに私のコード(最小化sniplet)です:

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

float kurv_steil, 
     kurv_korr, 
     t_abl_s, 
     t_out, 
     t_abl_s, 
     b, 
     t_tank_s; 

void main() 
{ 
    t_tank_s=32; 
    kurv_steil=0.85; 
    kurv_korr=-5; 
    t_out=1.44; 
    t_abl_s=24; 

    printf("Werte: k_steil: %f k_korr: %f t_out: %f t_abl_s: %f\n",kurv_steil,kurv_korr,t_out,t_abl_s); 
    b= pow(t_abl_s,(t_out/(320-(t_out*4))))*0.65*kurv_steil*b*(-t_out+20); 

    printf("[temp] Ganze Rechnung tank_s: %f\n",b); 
    b=320-(t_out*4); 

    printf("[temp] 320-(t_out*4) b: %f\n",b); 
    b=t_out/b; 

    printf("[temp] t_out/b b: %f\n",b); 
    b=pow(t_abl_s,b); 

    printf("[temp] t_abl_s^b b: %f\n",b); 
    b=0.65*kurv_steil*b; 

    printf("[temp] 0.65*kurv_steil*b b: %f\n",b); 
    b=b*(-t_out+20); 

    printf("[temp] b*(-t_out+20) b: %f\n",b); 
    b=2*b+t_abl_s+kurv_korr; 

    printf("[temp] 2*b*(-t_abl_s) b: %f\n",b); 
} 

出力は次のとおりです。

Werte: k_steil: 0.850000 k_korr: -5.000000 t_out: 1.440000 t_abl_s: 24.000000 
[temp] Ganze Rechnung tank_s: 0.000000 
[temp] 320-(t_out*4) b: 314.239990 
[temp] t_out/b b: 0.004582 
[temp] t_abl_s^b b: 1.014670 
[temp] 0.65*kurv_steil*b b: 0.560605 
[temp] b*(-t_out+20) b: 10.404831 
[temp] 2*b*(-t_abl_s) b: 39.809662 

私は、第1の出力を持つことが期待される "39.809662" の同じ値を持っていますしかし、それは常に "0"を持っています。どうして?

あなたは右側に変数bを使用している。このラインで
+1

コードをインデントして投稿し、英語で書くことで、人々が何かもっと理解できるようにします。 – LPs

+1

メインのシグネチャは 'int main(void)'または 'main(int argc、char * argv [])'であることができます。 – LPs

+0

簡単なことは、 '%f'ではなく数字を出力するための書式を変更することです。 '%.3f'または'%6.3f'です。 Cの数学は非常に正確です。結果が常に小数点でうまく表示されるとは限りません。 –

答えて

0

上記の問題は、使用している式に問題があります。あなたはb=... *b*...です。 bはこの時点では不明な値を持っています(ほとんどの場合、コンパイラは0に設定されています)。b=...*0*...の結果が0になります。

また、あなたが2* ... + t_abl_s+kurv_korr

あなたの式を追加する必要がありますので、公式の意志が

b= 2 * 
    pow(t_abl_s,(t_out/(320-(t_out*4)))) * 
    0.65 * kurv_steil * 
    (-t_out+20) + 
    t_abl_s + kurv_korr; 
4

b= pow(t_abl_s,(t_out/(320-(t_out*4))))*0.65*kurv_steil* b *(-t_out+20); 

。これは通常、プログラムが開始するときにゼロになります。したがって、それによって乗算されるものはゼロになります。特定の値を持つ変数に依存しないでください。常に変数を初期化してください。

+1

通常はいつですか?それは未定義であり、私はそれがゼロよりも頻繁にゼロでないと仮定します。確かに、それは重大な間違いの間にそれほど些細なことに聞こえる。 –

+3

@ KamiKazeこの場合、変数はファイルスコープで宣言されます。つまり、静的な記憶期間を持ち、したがって常にゼロです。 Cの標準で保証されているので、答えは正しいですが、 "典型的な"とは別に、ゼロになります。それでも、静的記憶域持続時間変数のゼロ初期化に依存するプログラムを書くのは悪い習慣です。 – Lundin

+0

@ Lundin明確化が大いに評価されます。 –

0

このリンクで見ることができるように、1.44はバイナリで表現することはできません。

http://www.wolframalpha.com/input/?i=1.44+in+binary

だから、あなたがそれを行う任意の浮動小数点計算が不正確になります。

もっとよく知られている例は1/3を表現しようとすることです。基底3では、単純に0.1です。 10進数では0.33333 ... 10進数は.44で終わる同じ考えです。バイナリで正確に表現することはできません。

0

みんなありがとうように見えます!

ああ男!私はとても愚かでした。はい、実際には、bが初期化されていない(とはっきりとランダムに常にゼロである)ので、常に "* b"が式に "0"となっていました。

計算の精度については、278.24が278.23999と同じではないと確信していません。反対側で、それは今私のために働く。

ありがとうございます!

+0

浮動小数点を使用するとすぐにエラーが発生します。それらを低く保つのはあなたの義務です。このため、==と浮動小数点を比較しません。たとえば、0.1 + 0.1 + 0.1 == 0.3を試してください。これはfalseにする必要があります。 –