4

16ビットマイクロコントローラーを対象としたCで書かれたコードがあります。このコードは基本的に多くの浮動小数点演算を実行します。

結果が正になるまで算術演算は正常に機能しますが、減算の場合、期待される結果が負の場合、ゼロになります。

result = 0.005 - 0.001;      Is correctly computed as 0.004
result = 0.001 - 0.005;      Is always zero.

なぜフロートにそのような振る舞いがあるのですか?

4

5 に答える 5

5

面白い。浮動小数点ソフトウェアの障害である可能性は非常に簡単です。組み込みシステムには、コード サイズを抑えるためにオプションとして浮動小数点が含まれることがよくあります。

最初のステートメントが機能するため、ここで問題があるかどうかはわかりません。

何が起こるか:

result = 0.005 - 0.001;
result = -result;

result = 0.002 - 0.001;
result = 0.002 - 0.002;
result = 0.002 - 0.003;

result = 0.001 - 0.002;
result = 0.001 - 0.003;
result = 0.001 - 0.004;

ここでの考え方は、何が原因であるかについて有用な情報を収集することであり、フォレンジックでよく行われます。これらの計算の結果は、実際の問題を特定するのに役立つ可能性があります。

コメントの結果に基づいて:

result = 0.005 - 0.001;  // 0.004
result = -result;        // 0.000
result = 0.002 - 0.001;  // 0.001
result = 0.002 - 0.002;  // 0.000
result = 0.002 - 0.003;  // 0.000
result = 0.001 - 0.002;  // 0.000
result = 0.001 - 0.003;  // 0.000
result = 0.001 - 0.004;  // 0.000

浮動小数点ライブラリに重大な欠点があるようです。さらに2つの質問:

  • 結果をどのように出力していますか (実際のコードを見せてください)。
  • どのマイクロコントローラーと開発環境を使用していますか?

印刷方法に問題があるか、環境の制限である可能性があります。

Ajit、私はあなたが本当にあなたを助けるために私たちにいくつかのコードを提供する必要があると思います. 必ずしも実際のコードではなく (実際のコードをリリースすることについての懸念は理解されます)、問題を示すものだけです。

あなたのコメントのいくつかに基づいて、ウィットに:

Adriaan さん、「結果」のデータ型は float、つまり 32 ビット表現 (単精度) です。私はシステム インターフェイスとしてCANを使用しているため、結果を 1000 倍して CAN バス経由で送信しています。-0.003 のような負の数である場合は、CAN メッセージで FF FD を期待しています。私はデバッガを持っていません。

完全に理解できているかわかりませんが、がんばってみます。

たとえば、-0.003 のような 32 ビットの浮動小数点数があり、それを 1000 倍して整数にします(0xFFFD は、-3 の 16 ビットの 2 の補数表現です)。では、次のようなコードを実行するとどうなるでしょうか。

int main(void) {
    float w = -0.003;
    int x = (int)(w * 1000);
    int y = -3;
    int z = -32768;
    // Show us you code here for printing x, y and z.
    return 0;
}

整数をテストしてほしい理由は、浮動小数点数とはまったく関係がない可能性があるからです。float 値は完全に正しいかもしれませんが、出力方法 (CAN メソッド) に問題があります。

「CAN」がある種のシリアル インターフェイスである場合、送信できるバイト数に制限がある可能性があります。上位バイトがパケット マーカーとして使用され、FF が実際にメッセージを途中で終了させるシナリオを想定できます。そのため、-32768 (0x8000) もテストしてください。

STMicroelectronicsが、負の浮動小数点数を処理できないほど頭がおかしいランタイム システムを作成するとは信じがたいことです。情報がどこか別の場所 (たとえば、「印刷」プロセスなど) で破損している可能性が高いと思われます。

于 2009-09-08T07:03:00.213 に答える
0

それは本質的にCのことではないので、あなたが言っていないことにかかっています:-

  • コントローラー(ST10どうやら)
  • コンパイラ(Cosmicソフトウェア?もしそうなら、標準に準拠しています)
  • 浮動小数点ライブラリ(コンパイラから?)
  • プログラム(それを実証する最も短い完全なプログラムが良いでしょう。)

浮動小数点から表示していないintに変換するキャストでしょうか?

于 2009-09-08T08:50:56.763 に答える
0

0.001 ~ 0.005 の結果を 5 文字のフィールドとして出力しようとしている可能性はありますか? その場合、結果は 0.0 に丸められて表示されます。

于 2009-09-08T07:24:04.523 に答える
0

マイクロコントローラには浮動小数点用のハードウェアがありますか? おそらくそうではありません。マイクロコントローラは一般にそうではありません。したがって、これは浮動小数点演算のソフトウェア実装におけるバグまたは制限である可能性があります。ドキュメントを探すか、ソースがある場合はそれを読んでください。

于 2009-09-08T07:03:15.343 に答える
0

より多くのコンテキストを提供できますか? この例では、コンパイル時に両方の定数が既知であるため、評価はおそらくコンパイラによって行われます。「結果」の種類は何ですか?(つまり、 IEEE-754ハーフまたはシングルまたはダブル?) これをどのように評価しますか? デバッガー、if ステートメント、または printf を使用していますか? 私がこれを尋ねている理由は、赤いニシンがあるかもしれないからです. たとえば、printf を使用して誤ってフォーマットすると、マイナス記号が表示されないことがあります。バイナリ表現 (つまり、32 ビットの場合は printf("%lx", result) による) を見て、符号ビットを確認します。

于 2009-09-08T08:26:36.300 に答える