C / C ++バイナリ検索

以下のように電圧と温度との対応関係は、デジタル値の電圧値がADCの値を表す検出した温度センサがあると、-AD温度値テーブルが形成されています。

 

 

カーブ、実質的に逆の関係。

 

ADCは、書かれた低レベルのドライバを有し、外部インターフェースは、リアルタイムでAD値を読み取るためのセンサを有していてもよいです。今ではによりAD値を読み出した後、必要バイナリサーチそれに対応する温度値を見つけることと、次に異なる構造、その後の使用のために他のモジュールに送られます。

 

バイナリ検索機能を書いて、それがそう考えることができます。

 

温度などのX軸、Y軸値としてAD値。機能は持って1つの入力と1つの出力を入力は、出力温度に対応する値が中に見出される、広告の価値を得るために、下インターフェースからのものです。まず、入力を受信し、元のパラメータとして、2つのパラメータを有していてもよく、後者は、定義された出力変数外部メモリへのポインタに設定されています。二つのテーブル(AD及び温度)、ならびにルックアップテーブルのサイズ範囲を制限するために:他のパラメータです。

 

だから、この関数は、このようなヘッドのように記述することができます。最初の二つは、CONST SW型ポインタテーブル2、テーブルの、入力および出力サイズです。(他のすべてのタイプの基礎は、SWは、符号付きワードを表すヘッダファイルに定義されている短いタイプを署名されています)

Bのlook_up_table_sw(CONST SW * p_XTable_SW、CONST SW * p_YTable_SW、UW TableSize_UW、SW ValueX_SW、SW * ValueY_SW)

 

タイプ機能が見つからないか、または見つかりません「B」Boolean型を返します。

 

次に、関数の実装を検討してください。

 

最初は、ポインタが空でないことを保証するために、安全性チェックする必要があり、テーブルがあります。

もし(p_XTable_SW!= NULL && p_YTable_SW!= NULL && TableSize_UW> 0 
{
    // ...... 
}

 

このステップは、少なくとも何の問題を確実にしないようにした後、その後、作業を​​開始。

 

まず、ADの値を見ては、ADの上下形態を超えない、さらに検索を越えて考慮される、温度値がそれぞれの最大値と温度の最小値としたが見つかりました。

もし(ValueX_SW <= p_XTable_SW [ 0 ])
{
    * ValueY_SW = p_YTable_SW [ 0 ]。 = TRUE;
}
そう であれば(ValueX_SW> = p_XTable_SW [TableSize_UW - 1 ])
{
    * ValueY_SW = p_YTable_SW [TableSize_UW - 1 ]。 = TRUE;
}

{
    // ...... 
}

 

他{}補助コードでは続行します。このとき、AD値は、ルックアップの範囲に記載され、以下のバイナリ検索に焦点を当てています。

 

バイナリ思考を見つけ、実際には、例えば、少し推測ゲームであってもよいです。

 

マジシャンは女の子に言いました:「あなただけの1-100番号をしたい、私はあなただけのそれぞれが大小推測言うと思い、私は10回以内にそれを推測することができるようになります。」まあ、女の子は(デジタルたかったですそれは)88である場合には、マジックは、すべての中間を推測、それが整数でない切り捨てられます。最初の推測50は、少女は、その後、マジシャンが一瞬誰でも思いつきそうする前に1から49まで、数の半分を除外しました。75秒の推測、少女は言いました。87は小型、三時間を推測します。ビッグ93の第四に推測。ビッグ90の第五の推測、。第六に88を推測しました。

 

バイナリサーチは、実際には非常に効率的な検索アルゴリズムですが、どのように頻繁にフォームを見つけるために、張テーブルの変更のためではなく、注文されたテーブルを必要とし、この要件は、ADおよび温度の値も明らかなように、 1、単純な関係を形成するために。

 

すべてのだから、最初の表現の推測を定義する中間推測の数を表す大小変数と変数を推測します。ループ内で続けて下さい、各サイクルは、中央のリフレッシュ推測の数を開始します。次のように構造化されました。

YOUR nLOW = 0x00で

YOUR nhighが = TableSize_UW - 1 

UW NMID =(nhighがNlow +)/ 2 

一方、(nLow < nhighが)
{ 
NMID =(nhighが+ nLow)/ 2。
// ...... }

 

続けながら{}補助コードで。どのような状況下でループを終了することを検討してください。

 

私はそれがいくつかの最初の、または最初の数である知っている、条件は下限が判決の最後にほとんどのセキュリティである上限未満で、かつ実際にはそれがある値を探しに確立することができます見つけることであるかを決定するためのサイクルを書きますエッジその上に少し。

 

例えば、私はそれは第三であることを知って、それは配列YにY軸(3)、私はそれが第三及び第四の間知っている、それはYであり、(3)及びY(4)の部屋には、戻すことができる計算何らかの方法(例えば補間など)で使用することができます。簡単に言えば、状況はこのループの外で、私はそれがアップしている場所を知っています

 

次のように補足しました。

もし(NMID == nLow)
{
    破ります;
}
そう であれば(((ValueX_SW> = p_XTable_SW [NMID])&&(ValueX_SW <= p_XTable_SW [NMID + 1 ]))||((ValueX_SW <= p_XTable_SW [NMID])&&(ValueX_SW> = p_XTable_SW [NMID - 1 ]) ))
{
    破ります;
}
それ以外の 場合(ValueX_SW> p_XTable_SW [NMID])
{
    nLow = NMID + 1 
}

{
    nhighが = NMID - 1 
}

 

あなたは自分の計算を見ることができ判決の終わりにはまだセキュリティは、ほとんどの時間NMID結果が切り捨てられ、最終的に下限が同じ値である場合は、最初。しかし、一般に、他の第二のループの外になり、この工程であればAD値の位置を決定します次いで、2つのケースが(ダウン、大きな推測推測)オリジナルの下限は、中間数は(推測アップ、小推測)となるようにするように、位置を特定し、又は天井が元の中間数になることはできませんでした。NMIDが更新されます各サイクルは、各重推測の数ですNMIDコードのアレイは、シリアル番号で示されています。

 

さて、ここで、私は正確にAD値を知っているが、3例があります。

①私は数(NMID)であることを起こると思います。

②私はそれが少し右側の数字だと思います。(NMIDと+ 1の間NMID)

③私はそれを左に少しの数だと思います。(NMIDとNMID-1との間)

 

取り扱いが最初、第1 NMID X軸はY軸に相当している、もちろん、NMIDの一つです。

もし(p_XTable_SW [NMID] == ValueX_SW)
{
    * ValueY_SW = p_YTable_SW [NMID]。 = TRUE;
}

 

第二と第三に対処する方法を、より良く理解するために、グラフを描きます。例えば、例以下、上記検索により取得されたAD値からインタフェースであり、それは、第2および第3の値の間で決定されます。NMIDは現在2、NMIDとNMID + 1の間に入ります。+もちろんの間、私はY軸の中にも、Bの温度を知りたいとNMID 1 NMID。

(単に逆の関係を示す直線を描きます)

 

ここで私は取る線形補間どれだけBを計算する方法を。線形補間は、隣接点間の直線を想定しているにおいて、傾きは同じです。

 

私たちはこのように、地元の絵を見て:

 

勾配が等しいか接線方法であってもよく、また、次の関係を得るために、同一の原理が短いであり、同様の三角形を使用することができます。

 

 

さらに:

 

 

第三种情况在左边,是完全一样的,只要整体减小一格,把原来的x(mid)替换成x(mid-1),原来的x(mid+1)替换成x(mid),y(mid+1)替换成y(mid),y(mid)替换成y(mid-1)就行了。

 

正比关系的推导过程是一样一样的。

 

因此三种情况的代码如下:

if (p_XTable_SW[nMid] == ValueX_SW)
{
    *ValueY_SW = p_YTable_SW[nMid];
    ret = TRUE;
}
else if (ValueX_SW < p_XTable_SW[nMid])
{
    *ValueY_SW = p_YTable_SW[nMid-1] - (ValueX_SW - p_XTable_SW[nMid-1]) * (p_YTable_SW[nMid-1] - p_YTable_SW[nMid]) / (p_XTable_SW[nMid] - p_XTable_SW[nMid-1]);
    ret = TRUE;
}
else
{
    *ValueY_SW = p_YTable_SW[nMid] - (ValueX_SW- p_XTable_SW[nMid]) * (p_YTable_SW[nMid]-p_YTable_SW[nMid + 1]) / (p_XTable_SW[nMid + 1] - p_XTable_SW[nMid]);
    ret = TRUE;
}

 

这样,二分查找函数就写完了,最后:

return ret;

 

整项工作要求的完整的二分查找函数的实现,放在lookup.cpp中,如下。

#include "lookup_pub.h"

B look_up_table_sw(const SW * p_XTable_SW, const SW * p_YTable_SW, UW TableSize_UW, SW ValueX_SW, SW *ValueY_SW)
{
    B ret = FALSE;

    if (p_XTable_SW != NULL && p_YTable_SW != NULL && TableSize_UW > 0)
    {
        if (ValueX_SW <= p_XTable_SW[0])
        {
            *ValueY_SW = p_YTable_SW[0];
            ret = TRUE;
        }
        else if (ValueX_SW >= p_XTable_SW[TableSize_UW - 1])
        {
            *ValueY_SW = p_YTable_SW[TableSize_UW - 1];
            ret = TRUE;
        }
        else
        {
            UW nLow = 0x00;

            UW nHigh = TableSize_UW - 1;

            UW nMid = (nHigh + nLow) / 2;

            while (nLow < nHigh)
            {
                nMid = (nHigh + nLow) / 2;

                if (nMid == nLow)
                {
                    break;
                }
                else if (((ValueX_SW >= p_XTable_SW[nMid]) && (ValueX_SW <= p_XTable_SW[nMid + 1])) || ((ValueX_SW <= p_XTable_SW[nMid]) && (ValueX_SW >= p_XTable_SW[nMid - 1])))
                {
                    break;
                }
                else if (ValueX_SW > p_XTable_SW[nMid])
                {
                    nLow = nMid + 1;
                }
                else
                {
                    nHigh = nMid - 1;
                }
            }

            if (p_XTable_SW[nMid] == ValueX_SW)
            {
                *ValueY_SW = p_YTable_SW[nMid];
                ret = TRUE;
            }
            else if (ValueX_SW < p_XTable_SW[nMid])
            {
                *ValueY_SW = p_YTable_SW[nMid-1] - (ValueX_SW - p_XTable_SW[nMid-1]) * (p_YTable_SW[nMid-1] - p_YTable_SW[nMid]) / (p_XTable_SW[nMid] - p_XTable_SW[nMid-1]);
                ret = TRUE;
            }
            else
            {
                *ValueY_SW = p_YTable_SW[nMid] - (ValueX_SW- p_XTable_SW[nMid]) * (p_YTable_SW[nMid]-p_YTable_SW[nMid + 1]) / (p_XTable_SW[nMid + 1] - p_XTable_SW[nMid]);
                ret = TRUE;
            }
        }
    }

    return ret;
}

 

其它补充的源代码附在后面。

 

App_Typedefine.h中对基础类型作宏定义。

#ifndef _APP_TYPEDEFINE_H_
#define _APP_TYPEDEFINE_H_

// ==== basic type ====
typedef unsigned char               UBYTE;
typedef signed char                 SBYTE;
typedef unsigned short              UWORD;
typedef signed short                SWORD;

typedef unsigned char               BOOL;
typedef unsigned char               BOOLEAN;

typedef float                       FLOAT;
typedef double                      DOUBLE;

typedef unsigned char                 APP_RESULT;
#define APP_E_NOT_OK                (0x01U)
#define APP_E_OK                    (0x00U)

typedef UBYTE UB;
typedef SBYTE SB;
typedef UWORD UW;
typedef SWORD SW;

typedef FLOAT F;

typedef BOOL  B;


//typedef void VOID
#define VOID      void

// Definition of local function
#define LOCFUNC   static

// Definition of a function    
#define PUBFUNC

// MACRO used for BOOL type
#ifdef FALSE
#undef FALSE
#endif
#define FALSE ((BOOL)0)

#ifdef TRUE
#undef TRUE
#endif
#define TRUE  (!FALSE)

// MACRO used for inline function, used for optimization
#ifdef  CSPLUS
#define INLINE 
#else
#define INLINE inline
#endif

// MACRO used for const
#ifdef CONST
#undef CONST
#endif
#define CONST    const

// MACRO used for static variable
#define LOCVAR   static

// MACRO used for static functions
#define LOCFUNC  static


// Keep Same as MPU_NULL_PST_GUARD_LowAddress
#define NULL_PST     ((void*)0xFEE00000)

// Definition of NULL-pointer
#ifndef NULL
#define NULL     (0)
#endif

// Definition of an invalid pointer value
#define PTR_INVALID (0xFEE00000)

#define NULL_POINTER(type) ((type *) PTR_INVALID)

// min-max-constants for integer data types
#define UB_MAX          ((UB)255)
#define UB_MIN          ((UB)0)

#define UBYTE_MAX       ((UB)255)
#define UBYTE_MIN       ((UB)0)

#define SB_MAX          ((SB)127)
#define SB_MIN          ((SB)-128)

#define SBYTE_MAX       ((SB)127)
#define SBYTE_MIN       ((SB)-128)

#define UW_MAX          ((UW)65535)
#define UW_MIN          ((UW)0)

#define UWORD_MAX       ((UW)65535)
#define UWORD_MIN       ((UW)0)


#define SW_MAX          ((SW)32767)
#define SW_MIN          ((SW)-32768)

#define SWORD_MAX       ((SW)32767)
#define SWORD_MIN       ((SW)-32768)

#define UL_MIN          ((UL)0)
#define UL_MAX          ((UL)4294967295)

#define ULONG_MIN       ((UL)0)
#define ULONG_MAX       ((UL)4294967295)

#define SL_MAX          ((SL)2147483647)
#define SL_MIN          ((SL)-2147483648)

#define SLONG_MAX       ((SL)2147483647)
#define SLONG_MIN       ((SL)-2147483648)

#endif

 

lookup_pub.h对查找函数作外部声明,引用了基础类型的头文件。

#ifndef LOOKUP_PUB_H_INCLUDED
#define LOOKUP_PUB_H_INCLUDED

#include "App_TypeDefine.h"

extern B look_up_table_sw(const SW * pSrcTable_SW, const SW * pDestTable_SW, UW TableSize_UW, SW ValueSrc_SW, SW *ValueDest_SW);

#endif 

 

HwaAdc_pub.h中定义了用于存值、供其它模块使用的结构体,以及adc处理函数的外部声明。

#ifndef _HWA_ADC_PUB_INCLUDED_
#define _HWA_ADC_PUB_INCLUDED_

#include "App_TypeDefine.h"

#define ADC_TABLE_SIZE      27

typedef struct
{
    UB state_UB;
    SW value_SW;
}HWA_TEMP_ADC_INFO_ST;

typedef struct
{
    HWA_TEMP_ADC_INFO_ST    TempInCar_st;
    // form ADC

}IF_HWA_ADC_READ_INFO_ST;

typedef struct
{
    IF_HWA_ADC_READ_INFO_ST Adc_st;

}IF_SRU_HWA_INFO_READ_PACKET_ST;

extern const SW HWA_ADC_AD_Table_SW[ADC_TABLE_SIZE];

extern VOID hwa_adc_process(VOID);

#undef EXTERN
#endif

 

HwaAdc.cpp定义了一个内联函数,用于把查到的温度值存到上面定义的结构体内。实现了adc处理函数,调用查找函数然后传送找到的温度值。为便于测试,所以写成下面这样,ad值自己手动输入,将传出去的结果显示出来。

其中定义的normvalue是起放大作用的,因为查找函数返回SW类型,查找后算的值也会向下取整,但是算出的有可能是个浮点数,那就体现不出小数点后面的精度了,所以先放大,再计算,最后返回的整数就能看到小数点后面几位

#include "lookup_pub.h"
#include "HwaAdc_pub.h"
#include <iostream>

//展现精度
#define normvalue 100

IF_SRU_HWA_INFO_READ_PACKET_ST                           hwa_t5_write_pst;

const SW HWA_ADC_AD_Table_SW[ADC_TABLE_SIZE] = {
    22,25,29,33,38,
    45,52,61,73,86,
    102,123,147,178,217,
    265,326,403,502,629,
    794,1010,1293,1670,
    2174,2856,3787
};

const SW HWA_ADC_INDOOR_TEMP_Table_SW[ADC_TABLE_SIZE] = {
    90 * normvalue,85 * normvalue,80 * normvalue,75 * normvalue,70 * normvalue,
    65 * normvalue,60 * normvalue,55 * normvalue,50 * normvalue,45 * normvalue,
    40 * normvalue,35 * normvalue,30 * normvalue,25 * normvalue,20 * normvalue,
    15 * normvalue,10 * normvalue,5 * normvalue,0 * normvalue,-5 * normvalue,
    -10 * normvalue,-15 * normvalue,-20 * normvalue,-25 * normvalue,
    -30 * normvalue,-35 * normvalue,-40 * normvalue
};

INLINE VOID VDB_Set_Temp_InCar_V(SW val_sw)
{
    hwa_t5_write_pst.Adc_st.TempInCar_st.value_SW = val_sw;
}

VOID hwa_adc_process(VOID)
{
    UW adc_value_uw;
    SW adc_value_sw;

    //TempInCar_sw
    //adc_value_uw = analog_if_query_channel(HWA_ADC_CH_INDOOR_TEMP);
    std::cout << "Enter ad value input:";
    while (std::cin >> adc_value_uw)
    {
        if (look_up_table_sw(HWA_ADC_AD_Table_SW, HWA_ADC_INDOOR_TEMP_Table_SW, ADC_TABLE_SIZE, (SW)adc_value_uw,
            &adc_value_sw))
        {
            VDB_Set_Temp_InCar_V(adc_value_sw);
        }
        std::cout << "ad value from analogif is " << adc_value_uw << ",";
        std::cout << "TEMP value set out is:" << hwa_t5_write_pst.Adc_st.TempInCar_st.value_SW << "\n";
        std::cout << "Enter ad value input:";
    }

}

 

最后是主函数main.cpp。

#include "HwaAdc_pub.h"
#include <stdlib.h>

int main()
{
    hwa_adc_process();

    system("pause");
}

 

测试结果

 

AD值刚开始输入21,超出范围, 所以温度取到90度。

输入23,24,可以看到是88.34度,86.67度。

 

おすすめ

転載: www.cnblogs.com/banmei-brandy/p/11766178.html