メインコンテンツ

CERT C: Rec.FLP02-C

精度の高い計算が必要な場合は浮動小数点数の使用を避ける

説明

ルール定義

精度の高い計算が必要な場合は浮動小数点数の使用を避けます。1

Polyspace 実装

ルール チェッカーは、"等号演算子による浮動小数点の比較" をチェックします。

すべて展開する

問題

等号演算子による浮動小数点の比較は、浮動小数点数に等価演算 (==) または不等式演算 (!=) を使用する場合に発生します。

Polyspace® では、以下の場合に浮動小数点数の等価演算および不等式演算の欠陥を報告しません。

  • 2 つの浮動小数点定数の間で比較が行われている。

        float flt = 1.0;
        if (flt == 1.1)
  • 定数と、有限のごく少数の値を取りうる変数の間で比較が行われている。

    float x;
    
    int rand = random(); 
    switch(rand) { 
    case 1: x = 0.0; break; 
    case 2: x = 1.3; break; 
    case 3: x = 1.7; break; 
    case 4: x = 2.0; break; 
    default: x = 3.5; break; }
    //…
    if (x==1.3) 
  • 整数値のみを含む浮動小数点式の間で比較が行われている。

    float x = 0.0;
    for (x=0.0;x!=100.0;x+=1.0) {
    //…
    if (random) break;
    }
    
    if (3*x+4==2*x-1)
    //…
    if (3*x+4 == 1.3)
  • オプション フラグ -detect-bad-float-op-on-zero を使用しない限り、オペランドの 1 つは 0.0 です。

    /* Defect detected when
    you use the option flag */
    
    if (x==0.0f) 

    ユーザー インターフェイスから解析を実行している場合は、[構成] ペインの [詳細設定] ノードにある [その他] フィールドにこのオプションを入力できます。Otherを参照してください。

    コマンド ラインで、解析コマンドにフラグを追加します。

    polyspace-bug-finder -sources filename ^
    -checkers BAD_FLOAT_OP -detect-bad-float-op-on-zero

リスク

浮動小数点の表現は不正確で丸め誤差を伴うため、2 つの浮動小数点値の等価性または非等価性のチェックは予期しない結果を返す可能性があります。

修正方法

次のように浮動小数点値の等価性をチェックする代わりに、

if (val1 == val2)
以下のように値の差が事前定義された許容誤差値 (たとえば、float.h に定義されている値 FLT_EPSILON) より小さいことをチェックします。
#include <float.h>
if(fabs(val1-val2) < FLT_EPSILON)

以下の修正例を参照してください。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

例 - for ループ内の浮動小数点の非等価性
#include <stdio.h>
#include <math.h>
#include <float.h>

void func(void)
{
    float f;
    for (f = 1.0; f != 2.0; f = f + 0.1)     //Noncompliant
        (void)printf("Value: %f\n", f);
}

この関数では、for ループで停止メカニズムとして f と数値 2.0 の非等価性をテストします。浮動小数点の表現は不正確なため、反復回数は特定が難しいか、無限大の可能性があります。

修正 — 演算子を変更

1 つの修正方法として、厳密性の低い別の演算子を使用することができます。たとえば、>= または <= などの不等式演算です。

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

void func(void)
{
    float f;
    for (f = 1.0; f <= 2.0; f = f + 0.1)    
        (void)printf("Value: %f\n", f);
}

チェック情報

グループ: Rec.05.浮動小数点 (FLP)

バージョン履歴

R2019a で導入


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.