• 締切済み

テーブルからの検索一番近いインデックスを取得

こんにちは。 floatのテーブルからどこに一番近いかを知りたいのですがどのようにしたらよろしいのでしようか。 単純に二分探索でやってみましたが検索順序の関係で必ずしも近いところになりません。 ------------------------------------------------------------------ int binSearch( float fKey, const float* tblfData, int nNumData ) { int nFirst = 0 ; int nLast = nNumData - 1 ; int nComp ; float nComped ; // 探索範囲がなくなったら終了 while( nLast - nFirst > 0 ) { nComp = ( nFirst + nLast ) / 2 ; nComped = tblfData[ nComp ] - fKey ; if(fabsf( nComped ) <= FLT_EPSILON ) { return nComp ; } if(nComped <= 0 ) { nFirst = nComp + 1 ; } else { nLast = nComp - 1 ; } } if(nLast - nFirst < 0 ) { return nLast ; } return nFirst ; } int _tmain(int argc, _TCHAR* argv[]) { float tblsData[ 10 ] ; tblsData[ 0 ] = 0.000f ; tblsData[ 1 ] = 0.025f ; tblsData[ 2 ] = 0.050f ; tblsData[ 3 ] = 0.075f ; tblsData[ 4 ] = 0.100f ; tblsData[ 5 ] = 0.125f ; tblsData[ 6 ] = 0.150f ; tblsData[ 7 ] = 0.175f ; tblsData[ 8 ] = 0.200f ; tblsData[ 9 ] = 0.225f ; int i ; float fKey = -0.01f ; int nRet ; for( i=0; i<40; i++ ) { nRet = binSearch( fKey, tblsData, 10 ) ; if( nRet >= 0 ) { printf( "%.3f : %d : %.3f\n", fKey, nRet, tblsData[ nRet ] ) ; } else { printf( "%.3f :error\n", fKey ) ; } fKey += 0.01f ; } return 0 ; } ------------------------------------------------------------------ 上記のソースで0.060のとき0.050に近いのでbinSearchの戻り値は2を期待したいのですが、 3が返ってきてしまいます。 二分探索しか知りませんでしたので試してみましたが他の方法でもっと適切なのがありましたら 教えていただけないでしょうか。

みんなの回答

noname#212058
noname#212058
回答No.1

以下の2か所を直せば良いかと。 ・1か所目:binSearch メソッドの while の条件  while( nLast - nFirst > 1 )  ⇒ 探索するのは「値と一致するデータ」ではなく「値が存在する区分(範囲)」    なので、条件はゼロではなく 1 になります。 ・2か所目:binSearch メソッドの最後の値を返すところの条件  if ( fabsf( tblfData[nLast] - fKey ) <= fabsf( tblfData[nFirst] - fKey ) )  {   return nLast ;  }  return nFirst ;  ⇒ nLast と nFirst でより探索値に近いほうを選ばなくてはなりません。

zakubaran_2011
質問者

お礼

早々の返答をありがとうございます。 定時して頂いた方法でうまくいきました。 考察が足りませんでした。 助かりました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 10個で改行したいのですが

    int _tmain(int argc, _TCHAR* argv[]) { int i,n,j,w,m,; printf("素数は\n"); n=0; for(i=1; i<=2000; i++){ n=n+i; w=0; for(j=1; j<=i ;j++){ m=i%j; if(m==0){ w=w+1; } } if(w==2){ printf("%d、",i); } } return 0; } このプログラムは2000までの素数を出力するプログラムです。この結果の素数10個ずつで改行したいのですが、どうすればよいでしょうか? お願いします。

  • c++ TCHARで文字化け

    TCHARはUNICODEが扱えるときいたので早速つかってみた。以下は引数を表示するプログラムである。 Visual C++ Express Editionを使った。 #include <stdio.h> #include <tchar.h> int _tmain(int argc, _TCHAR* argv[]) { int i=0; while(i<argc){ _tprintf(_T("%s\r\n"),argv[i++]); } return 0; } しかし上記プログラムに日本語の引数をわたすと文字化けするではないか。なでしょうか?

  • C++の質問です!

    課題なんですけど分からないです(泣) 解答お願いします(;;) 下記のプログラム中の(1)~(7)には何が入るか? #include <stdafx.h> (3) sho((4)) //関数sho の定義 { return((5)m/n); } void irekae(int (6),int (7)) //関数irekae の定義(2つの引数をp,q とする、型に注意!) { int k; k=(6); (6)=(7); (7)=k; } int _tmain(int argc, _TCHAR* argv[]) //関数_tmain の定義 { int i,j; double x; printf("整数i,j?:"); scanf("%d%d",&i,&j); (1); //整数i,j を引数として実数除算した商を返す関数sho を呼び出す。 printf("i/j=%f¥n",x); //結果の確認 (2); //整数i,j の値を入れ換える関数irekae を呼び出す。 (1); printf("i/j=%f¥n",x); }

  • 解の個数の求め方

    1~500までの数字のうち、3と5で割り切れる数の個数を求める問題で, int _tmain(int argc, _TCHAR* argv[]) { int n=0; for(n=1;n<=500;n=n+1) if((n % 5)==0 && (n % 3)==0) printf("%d\n",n); return 0; } ここまでは出来たのですが、これだと解は出てきますが、個数ではないので、問題の趣旨と違いますよね; どうやればいいのか、だれか教えてくれませんか?

  • _TCHAR*での引数の読み込み

    VC++2010での、通常の #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { return 0; } のウィザードを使って、arvg[1]やargv[2]に引数を与えて、本体内で通常のCで使う printf("%s\n", argv[1]); や fopen(argv[1], "r"); を使いたいのですが、引数の型が_TCHAR*になっているため文字がそのまま使えません。 int main(int argc, char *argv[]) で使えば問題なく使えるのですが、デフォルトのウィザードを使った時の使い方を知っておきたいのです。 御経験のある方、御教示お願い致します。

  • C言語のフローチャート

    昨日に引き続き失礼します。下記のプログラムを作成したのですがフローチャートは、どのように書けばいいのでしょうか? #include "stdafx.h" #include <stdio.h> int _tmain(int argc, _TCHAR* argv[]) { char ss[10] = "abcdefg"; char *ssp; ssp =ss; while (1){ if (*ssp ==0) break; printf("文字 *ssp=%c\n",*ssp); ++ssp;} int ary[10] = {1,2,3,4,5,6,7,8,9,10}; int *pt; pt = ary; while (1) { if (*pt == 10) break; printf("値 *pt=%d\n",*pt); ++pt;} return 0; }

  • _putts、_putwsが実行されない

    #define _UNICODE #define UNICODE #include <stdio.h> #include <tchar.h> int _tmain() { TCHAR tStr[] = _TEXT("あ"); int errCode; printf("%d\n", WEOF ); errCode = _putts( tStr ); if( errCode == WEOF ){ printf("errCode is WEOF\n"); } return 0; } なぜか_puttsが成功せず、プロンプトにも文字は表示されません。 原因が分からないのですが、初歩的なことだと思います・・。 よろしくおねがいします。

  • 文字配列から数値への変換

    MicrosoftのVisual-Studio 2005を使っています。 C/C++については、ほぼ素人で、困っています。 下記のような簡単なソースで、 456 012 678 を表示するようにしたいのですが、できなくて困っています。 最初の 123 789 345 は下記のソースで表記できたのですが、どうすればよいの でしょう? 数値をわざと文字列で読み込んで、これを 数値に変換しているのでややこしいのかもしれませんが、 できればこれでやりたいので、申し訳ありませんが、教えていただ けないのでしょうか。よろしくお願いします。 #include "stdafx.h" #include "stdlib.h" char str[3][200] = { "123 456", "789 012", "345 678" }; int _tmain(int argc, _TCHAR* argv[]) { int a[10]; for (argc = 0; argc < 3; argc++){ a[argc] = atof(str[argc]); printf("%d\n", a[argc]); }; return 0; }

  • ポインタのポインタ

    #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv){ int i; if(argc != 2) { fprintf(stderr, "Usage: %s vector\n\tEx: %s 11110000\n", argv[0], argv[0]); return 1; } for(i=0;i<8;i++){ if(**argv == '0'){ printf("%d\n",i); } else{ printf("A%d\n",i); } argv++; } return 0; } コンパイルして./a.exe 10010011などと入力しても A0 A1 Segmentation Faultとなります。 どうすれば、 A1 0 ・・・省略 for文で回した8回分、出力が可能になるのか教えてください。 初歩的な質問ですいません。

  • じゃんけんゲームをつくったのですが・・・。

    自分でじゃんけんゲームを作ってみたのですが、他の人のソースで どういう風に組んでいるのか研究したいのでソースお願いします。 後、もっとこういう風にした方がいいとおもう所があればおねがいします。 <ソース> #include<stdio.h> #include<time.h> #include<stdlib.h> int main() { int i; int n; srand(time(NULL)); n=rand()%3; printf("じゃんけんをします,0がグーで1がチョキで2がパーです\n"); printf("じゃんけんぽい!"); scanf("%d",&i); if(i==0&&n==0){ printf("あいこです\n"); } else if(i==0&&n==1){ printf("勝ちました\n"); } else if(i==0&&n==2) { printf("負けました\n"); } if(i==1&&n==0){ printf("負けました\n"); } else if(i==1&&n==1){ printf("あいこです\n"); } else if(i==1&&n==2) { printf("勝ちました\n"); } if(i==2&&n==0){ printf("勝ちました\n"); } else if(i==2&&n==1){ printf("負けました\n"); } else if(i==2&&n==2){ printf("あいこです\n"); } if(i>2) { printf("やりなおしてください\n"); } return 0; }