最大値と最小値の間を循環する変数の最適な方法

このQ&Aのポイント
  • 最大値と最小値の間を循環する変数の実装方法について悩んでいます。
  • 現在のコードでは、if文を使用して加算と減算を判定していますが、もっと簡潔な方法はないか考えています。
  • 例えば、counter %= (MAX + 1) のような処理を実装すれば、加算の場合は問題なく動作しますが、減算の場合にはうまく動作しません。
回答を見る
  • ベストアンサー

最大値と最小値の間を循環する変数

最大値と最小値の間を循環する変数 最大値と最小値(ゼロ)の間を循環する変数counterを考えています。 以下が私が考えたコードです。 if (plus) { counter++; if (counter > MAX) counter = MIN; } else if (minus) { counter--; if (counter < MIN) counter = MAX; } else { ; } これで一応動くのですが、いかにもダサイので、もっと上手い方法が無いかと悩んでいます。 例えば、counter %= (MAX + 1) とでもすれば、加算の場合は上手くいく(?)のですが、減算の場合は上手くいきません。 何か良い方法は無いでしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.5

MIN≦counter≦MAXで循環させるのに、Xで割った余りを使いたいのなら、 0~X-1の範囲になるように変形する必要があります。 全辺から MINを引くと 0≦counter-MIN≦MAX-MIN なので、 counter - MIN を MAX-MIN +1で割った余りを使うことになります。 引いたMINは改めて足せば元の範囲になります。 加算 counter = MIN + ( ( counter - MIN ) +1 ) % (MAX - MIN + 1) ; 減算:負の%演算はややこしいので、1周期分加えて正の値にする counter = MIN + ( ( counter - MIN ) - 1 + (MAX - MIN + 1)) % (MAX - MIN + 1) ; 自分で書いといてなんですが、正直、わかりずらいです。 それに、整数演算の中では、割り算はもっとも時間のかかるものです。その意味ではこの方法は効率的とは言えません。 値の変化が任意(+50とか*15とかする)なら、割り算を使うのが効果的かもしれませんが。 私が作るなら、この質問にあるようなif文を使うか、三項演算子を使うか、ですね。 加算 counter = (counter == MAX) ? MIN : (counter + 1) ; 減算 counter = (counter == MIN) ? MAX : (counter - 1) ;

xuhuang
質問者

お礼

御回答ありがとうございます。 なるほど、三項演算子という手段がありましたか。 これが総合的に見て一番優れている気がします。 割り算を使用する方法も、適用するかどうかは別として、自力で考えつく位にはなりたいものです。

その他の回答 (5)

  • hiropuri
  • ベストアンサー率55% (24/43)
回答No.6

とりあえず、最後のelseは不要ですよね。 それと、plus と minus はそれぞれ個別でbool定義されて いますが、それは必須でしょうか? 無駄なような気が……? 既に色々な手法が提案されていますので、自分は「その他案」を。 例えばint型配列にて{ 1, -1} を定義すれば、以下の形が可能です。 c が 0 ならインクリメント、1 ならデクリメントされるという事ですね。 counter += tbl[c]; if (counter < MIN) counter = MAX; if (counter > MAX) counter = MIN; 判り易いので自分はこんな風に書く時もあるのですが、これを 人にオススメしていいのかは判りません……(^^;

xuhuang
質問者

お礼

御回答ありがとうございます。 質問の本筋以外は、例を示す為に適当に書いたものなので、深く突っ込まないで頂けるとありがたいです。 この方法も面白いですね。 ややトリッキーな感じなので、個人で書くプログラム以外では使用しづらいですが、知識として蓄えておきます。

回答No.4

FIFO(循環バッファ)のようなものであれば バッファの大きさを2の階乗にすると char buffer[256]; unsigned char read_p, write_p; //書き込み buffer[write_p++] = data; //読み込み if (read_p != write_p)  data = buffer[read_p++]; と書けます。バッファが128バイトであれば char buffer[2^7]; unsigned int read_p, write_p; //書き込み buffer[write_p++] = data; write_p &= (sizeof(buffer) - 1); //読み込み if (read_p != write_p) {  data = buffer[read_p++];  read_p &= (sizeof(buffer) - 1); } となり、if文が省略できて高速です。 またCPUによっては、バッファのサイズが256でもインデックスをunsigned intにして128と同様に記述した方が速い場合があります。 バッファの定義をアセンブラで記述して、アライメントを2の階乗に揃えた場合、インデックスではなくてポインターが使用できるのでより高速になります。

xuhuang
質問者

お礼

御回答ありがとうございます。 想定した回答よりも随分高度なものですが、参考にさせて頂きます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

正直なところ, 今のコードのままでいいんじゃないの? 無駄に凝るよりシンプルでいいと思うんだけどなぁ.... まあ「全ての実行パスで所要クロック数を統一したい」というならそれはそれでいいけど, かえって面倒な感じしかしない. ちなみに「MAX 以上 MIN 以下の間を動く」んだったら, counter %= MAX+1; じゃダメだよね.

xuhuang
質問者

お礼

御回答ありがとうございます。 確かに、実際の現場では、わかりやすさを優先してこのように書くかもしれません。 ただ、知っているのと知らないのとでは大違いなので、質問自体は意義があると思いたです。

  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.2

plus minus MAX MIN の意味がわかりませんので、一応動くといわれましても にわかに信じがたいです。

xuhuang
質問者

補足

御回答ありがとうございます。 質問とは直接関係ない部分だと思ったので、質問をシンプルにするつもりで省略してしまいました。 plus・minusには特に意味はなく、単に真になったらインクリメントもしくはデクリメントするといった程度の意味です。 MINとMAXは最小値と最大値で、counterを0~9の間で循環させたいなら、MINは0でMAXは9になります。 適当なところでdefineされているイメージです。 以上、捕捉になっているでしょうか。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

増やす場合… counter = (counter + 1) % MAX; 減らす場合… counter = (counter + (MAX - 1)) % MAX; ってコトですか?

xuhuang
質問者

お礼

御回答ありがとうございます。 この方法ならば、大分すっきり書けます。 実際のcounterの最大値は(MAX-1)になるのですよね? ただし、それはどうとでも対処できそうです。

関連するQ&A

  • Excel2003 VBA 最大値と最小値の求め方

    自分でいろいろ調べてみたのですが、ちょっとわからなくて質問させて頂きます。 VBAのコードにMINとMAX関数を入れて日付の最大値と最小値を求めたいのですがうまくいきません。 処理の初めに、対象の列には書式をYYYY/MM/DDの書式にし、そのあと最大値と最小値を変数に入れて求めています。 値を入れる変数はデータ型にしています。 表には2008/3/12など表示されているのに、MAX,MINともに変数の値は0でした。 どうしてこうなるのか見当もつきません。 よろしければ、返答お願いします。

  • C言語 最大値と最小値を求めて表示するプログラム

    はじめまして。 C言語を学習中です。 下記の問題演習の解答として記載されているプログラムがどうしても理解できません。 特にプログラムの最後の方のwhile文で最大値と最小値の判定をしているのかと思いますが、どのような計算をして判定しているのでしょうか。 while (array[i] != -1) { if (array[i] > *max) *max = array[i]; if (array[i] < *min) *min = array[i]; i++; 具体的に教えてください。 よろしくお願い致します。 ●問題 0~100の範囲で入力された複数の数値の中から、 最大値と最小値を求めて表示するプログラムを作成せよ。 -1が入力された場合は入力の終わりと判定する。 ただし、最大値と最小値はmain関数以外の一つの関数の中で求める。 また、入力された数値を記憶する配列の要素数は10とし、 それ以上入力された場合はエラーが起きても仕方ないこととする。 ヒント:配列の中に -1 があればデータの終わりだと判断できる。 ヒント:最小値を探すには、最大値を記憶した変数との比較を繰り返せば良い。 ●解答 #include <stdio.h> void maxmin(int array[],int *max,int *min); int main(void) { int i = 0,array[10],max,min; do { printf("%d 番目の数:",i + 1); scanf("%d",&array[i]); i++; } while (array[i - 1] != -1); maxmin(array,&max,&min); printf("最大値 %d : 最小値 %d\n",max,min); return 0; } void maxmin(int array[],int *max,int *min) { int i = 0; *max = 0; *min = 100; while (array[i] != -1) { if (array[i] > *max) *max = array[i]; if (array[i] < *min) *min = array[i]; i++; } }

  • 最大値と最小値の求め方

    以下はコマンドライン引数で任意の数の整数を受け取って、合計・平均・最大・最小を求めようとしたソースです。 しかし、実行したら最大値と最小値が正しく出ませんでした。 if文が間違っているのかもしれないと思ったのですが、はっきりと『ここが間違っている』という場所が分かりません。 どうかご指摘お願いします。 class Choco { public static void main (String[] args) { int i; int sum = 0; int max; int min; for ( i=0; i<args.length; i++) sum += Integer.parseInt(args[i]); double ave = sum/args.length; max = args.length; min = args.length; if (args.length>max){ max = args.length; } if (args.length<min){ min = args.length; } System.out.println("合計は" + sum + "です。"); System.out.println("平均は" + ave + "です。"); System.out.println("最大値は" + max + "です。"); System.out.println("最小値は" + min + "です。"); } }

    • ベストアンサー
    • Java
  • 2変数関数の最大値、最小値の求め方について

    2変数関数の最大値、最小値の求め方についてお教えください。 f(x,y) = sin(x)sin(y)sin(x+y) について、変数の範囲が 0 ≦ x ≦ π , 0 ≦ y ≦ π/2 の場合の最大値、最小値を求めよ。 範囲が指定されている場合の最大、最小についての解き方がわからないのでよろしくお願致します。

  • 最大値と最小値を表示したいのですが・・・

    double numに入っている数字から最大値と最小値を求めたいのですが、このままだと両方とも1.000になってしまうんです・・・ どうやったらちゃんと最大値と最小値が表示されるのでしょうか?? 初心者なものでスイマセンが教えてください!! #include<stdio.h> int main(void) { int i,j; double num[]={4.5,3.1,7.0,9.2,1.0,5.7,9.3,2.3,0.3,1.0}; double max,min; for(i=0; i<10; i++) { for(j=0; j<10; j++) { if(num[i]>num[j]) max=num[i]; } } for(i=0; i<10; i++) { for(j=0; j<10; j++) { if(num[i]<num[j]) min=num[i]; } } printf("最大値は%fです。",max); printf("最小値は%fです。",min); return 0; }

  • 三次関数の最大値・最小値

    グラフの大体のイメージはつくれるんですがよくわかりません。 具体的な問題ですが y=2x^3+3x^2-12xで xのとる範囲が[-3,+3]であるときの最大値、最小値なのですが 自分なりの答えはx=3のときmax45で、x=1のときmin-7 なのですがグラフを書いて最大値、最小値の 見当をつけて計算でだしたのですが、何かいい方法があったら教えてください。

  • 入力された入力値と最大値、最小値を表示させるプログラムで、最大値と最小

    入力された入力値と最大値、最小値を表示させるプログラムで、最大値と最小値のプログラムを下記に作成してみたら最小値が0になりました。そして、もう一つ繰り返し文を作ってみたら、最大値・最小値がうまく表示されました。この違いはどうしてですか?教えてください。 import java.io.*; class Hairetu1 { public static void main(String args[]) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.print("データはいくつですか?"); String str = br.readLine(); int num = Integer.parseInt(str); int a[]=new int[num]; int i; int max=0; int min=a[0]; for(i=0; i<a.length; i++){ System.out.print((i+1)+"番目は?"); str = br.readLine(); int tmp = Integer.parseInt(str); a[i] = tmp; if(max<tmp){ max=tmp; } if(min>tmp){ min=tmp; } } System.out.println("入力した値は"+test.length); System.out.println("最大は"+max); System.out.println("最小は"+min); } }

    • ベストアンサー
    • Java
  • 配列で最大・最小値を求める

    import java.io.*; class Prog10_2 { public static void main(String args[])throws IOException { System.out.println("10個の整数を入力してください。"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int num[] = new int[10]; for(int i=0; i<num.length; i++){ String str = br.readLine(); int tmp = Integer.parseInt(str); num[i] = tmp; } int max = 0; int min = 0; for(int i=0; i<num.length; i++){ if(max < num[i]){ max = num[i]; } if(min > num[i]){ min = num[i]; } } System.out.println("最大値は"+max+"で、最小値は"+min+"です。"); } }   というコマンドを実行すると、最大値はちゃんと表示されるのですが、 最小値はいつも"0"しか表示されません。どこを修正すればいいのでしょうか? どなたか分かる方いらっしゃいましたら、よろしくお願いします。

    • ベストアンサー
    • Java
  • int型変数の簡潔なプログラム

    #include<iostream> using namespace std; int main(void){ int max = a; int min = a; if(a > b){ min = b; }else{ max = b; } cout << "小さい方の値は" << min << "です。\n"; cout << "大きい方の値は" << max << "です。\n"; } これの、    int max = a; int min = a; と     if(a > b){ min = b; }else{ max = b; } が解りません。 何故変数をaからbにチェンジしているのでしょうか 初心者なのでお手柔らかにお願いします。 よろしくお願いします。

  • 最大・最小値の表記の仕方、これは駄目ですか?

    高校の教科書の問題などで、最大値・最小値を求めよ。 という類の問題はよくありますよね。 その解答を書くときに、 Yの最大値 ○ Yの最小値 ◇ といちいち「最大値、最小値」書くのは面倒なので、 yの横に小さくmax、またはminと書いて Ymax=○ Ymin=◇ と書きたいのですが この表記、使っていいものなのでしょうか? この表記は世間で認められているものなのでしょうか? 専門の方、分かる方いましたら、お願いします。

専門家に質問してみよう